home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1995 May / cd Ware (Juegos) Epimundo.iso / DOS / C / LLIST.ZIP / LISTLIST.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-26  |  83.0 KB  |  3,280 lines

  1. /* ------------------------------------------------------------------------------
  2. | FILE NAME: ListList.c
  3. |
  4. | DOCUMENT: [187.5]
  5. |
  6. | PURPOSE: To organize data of any type held anywhere in memory.
  7. |
  8. | KEY WORDS: DATA, LINKED LIST, SORT, SEARCH 
  9. |
  10. | OVERVIEW: 'ListList' is an easy-to-use linked list manager.  It solves the 
  11. | general problem of how to handle odd pieces of data held anywhere in memory.  
  12. | Comes complete with a user's guide, source code for over 100 carefully 
  13. | explained procedures and a comprehensive test program.  Features a 
  14. | fast method for sorting long lists. Written in portable ANSI 'C'.  
  15. | Distributed on a Try-Before-You-Buy basis: price $5, see 'USAGE TERMS' below.
  16. |
  17. |------------------------------------------------------------------------------
  18. |
  19. | DESCRIPTION: 'ListList' is a system of routines for managing general-purpose 
  20. | linked lists.
  21. |
  22. | The form of lists in this system can be pictured as follows:
  23. |
  24. |                      [ListRecord]
  25. |                           |
  26. |                      [ItemRecord]<-->[ItemRecord]...
  27. |                           |               |
  28. |                         [Data]          [Data]
  29. |
  30. | Each list consists of two types of records: ListRecords and ItemRecords.
  31. |
  32. | The purpose of the ListRecord is to provide a fixed point of reference
  33. | for accessing items contained in the list.
  34. |
  35. | The purpose of the ItemRecord is to associate items with one another and
  36. | with the data they refer to.
  37. |
  38. | The purpose of the data is determined by your application.
  39. |
  40. | See 'ListList.h' for a detailed description of the fields contained
  41. | in List and Item records.
  42. |
  43. | Usage is not limited to lists of strings: any kind of data located 
  44. | anywhere in memory can be itemized and manipulated via lists.
  45. |
  46. | Each procedure is explained in a comment header preceeding the source 
  47. | code for the procedure.
  48. |
  49. |------------------------------------------------------------------------------
  50. |
  51. | USAGE TERMS:
  52. |
  53. | This is commercial, for-profit software.  As the author, my terms are 
  54. | strict but easy to meet: you may use my software if you pay me $5 cash.  
  55. |
  56. | This is a good deal for both of us: you gain by saving several weeks of 
  57. | your most precious resource and I gain by earning my living. 
  58. |
  59. | Use of 'ListList' in software for profit or pleasure is encouraged.  
  60. | You may resell 'ListList' as part of your product without any 
  61. | limitations.  Feel free to edit the source to fit your style and add 
  62. | functions of your own.
  63. |
  64. | However, there is one usage restriction: use by government or non-profit 
  65. | organizations is prohibited.
  66. |
  67. | If you want to use ListList, the price is $5 cash with payment is due 
  68. | when you have saved more than $5 worth of your time by using it.  
  69. |
  70. | Please mail cash payment to my permanent address: 
  71. |
  72. |    LEE MALONE
  73. |    1800 MARKET ST. #221
  74. |    SAN FRANCISCO, CA  94102
  75. |
  76. | If you have more time than money, you can pay me in another way by 
  77. | helping to distribute my product.  Upload an unaltered copy of 'ListList.ZIP' 
  78. | to a new BBS or software library and you will have paid me in full.
  79. |  
  80. | I value your business.  Comments welcome.
  81. |
  82. | Sincerely,
  83. |
  84. | Lee Malone
  85. |
  86. |------------------------------------------------------------------------------
  87. |
  88. | WARRANTY:  I take pride in the quality of my work and stand by it.  
  89. | I warrant this product to be free of errors and will gladly send a 
  90. | full refund and a correction if you find an error that I missed.  
  91. |
  92. |------------------------------------------------------------------------------
  93. |
  94. | PACKING LIST:
  95. |
  96. | There are 9 files in the 'ListList' product:
  97. |
  98. |    ListList.DOC...ListList 5.0 User's Guide
  99. |    Bytes.c........Byte manipulation procedures
  100. |    Bytes.h........Byte library interface file
  101. |    DataSize.h.....Compiler-specific definitions
  102. |    ListList.c.....List manipulation procedures
  103. |    ListList.h.....List library interface file
  104. |    ListTest.c.....Test and example program
  105. |    Strings.c......String manipulation procedures
  106. |    Strings.h......String library interface file
  107. |
  108. | Shipped in compressed form as 'ListList.ZIP'.
  109. |
  110. |------------------------------------------------------------------------------
  111. |
  112. | GETTING STARTED: Running the Test Program
  113. |
  114. | 'ListList' has been fully tested and is free of errors, but you should 
  115. | compile and run the test program, 'ListTest.c', to make sure that it
  116. | works properly with your compiler.  Some revision to the data types in 
  117. | file 'DataSize.h' may be required for your system.  
  118. |
  119. |------------------------------------------------------------------------------
  120. | HISTORY: 01.04.89 by Lee Malone
  121. |          01.05.89 Completed writing Data Interface & Testing Operations
  122. |          01.09.89 Completed writing Construction Operations
  123. |          01.10.89 Moved from More to text file and compiled & tested.
  124. |          01.11.89 Wrote & tested sort operations, wrote some test routines.
  125. |          01.12.89 Added future enhancement documentation.
  126. |          02.02.89 Added DeleteAllItemsFromAListThatMatchAAddressOfData
  127. |          07.09.89 Upgraded lists to new format
  128. |          07.19.89 Fixed errors in ExchangeItems, SortAscending, SortDescending
  129. |          10.11.89 Deleted ItemNamePointer, ListNamePointer, 
  130. |                   and DataTypeID fields (to save space)
  131. |          11.29.91 Ported to Focus Project.
  132. |          10.25.93 Revised to conform to Focus usage.
  133. |          10.26.93 The term 'node' replaced with 'item' for clarity.
  134. |          11.22.93 Rev 5.0 
  135. |
  136. |----------------------------------------------------------------------------- */
  137.  
  138. #include <ListList.h>
  139.  
  140. /* --------------------------- EQUATES ---------------------- */
  141.  
  142. /* You can set the size of the list stack with this equate. */
  143. #define    MaxListStackItems    100
  144.  
  145. /* ------------------------- DATA ------------------------- */
  146.  
  147. AddressOfList        ListSpace;        /* Base address of list space.    */
  148. AddressOfItem        ItemSpace;        /* Base address of item space.    */
  149. Quad                 CountOfFreeLists; /* Lists available for use.       */
  150. Quad                 CountOfFreeItems; /* Items available for use.       */
  151. Quad                 MaxCountOfLists;  /* How many lists can exist.      */
  152. Quad                 MaxCountOfItems;  /* How many items can exist.      */
  153. AddressOfList        FirstFreeList;    /* 1st record in free list chain. */
  154. AddressOfItem        FirstFreeItem;    /* 1st record in free item chain. */
  155.  
  156. AddressOfList        TheList; /* The current list. */
  157. AddressOfItem        TheItem; /* The current item. */
  158.  
  159. Pair                 TheListSystemIsSetUp = 0; 
  160.                     /* A counter which is incremented
  161.                      * each time the list system is
  162.                      * set up, and decremented each
  163.                      * time it is cleaned up.
  164.                      * This allows multiple calls to
  165.                      * set-up/clean-up procedures
  166.                      * without causing problems.
  167.                      */
  168.  
  169. Quad                 TheListStack[MaxListStackItems];
  170. Quad                 TheListStackIndex;
  171.  
  172. Quad                 DirectAccessTableThreshold = 20;
  173.                     /* Quantity of items, above which a         */
  174.                     /* direct access table is used for sorting. */
  175.                     
  176. /* --------------------- PROCEDURES ----------------------- */
  177.  
  178. /*------------------------------------------------------------
  179. | NAME: BuildDirectAccessTableForList
  180. |
  181. | PURPOSE: To build a structure which permits direct access to 
  182. |          the items of a list.
  183. |
  184. | DESCRIPTION: Normally a linked list is accessed sequentially 
  185. | but there are some situations where direct access of items 
  186. | is needed. This procedure builds an index which can satisfy 
  187. | this requirement. 
  188. |
  189. | A Direct Access Table is just an array of item record 
  190. | addresses.
  191. |
  192. | Direct access tables are dynamically allocated using
  193. | 'AllocateMemory()'.
  194. |
  195. | The overall size of a direct access table depends on the
  196. | number of items in the list that it is created from:
  197. |      table size = ItemCount X sizeof(AddressOfItem)
  198. |
  199. | Use the 'FreeMemory()' procedure to discard useless
  200. | direct access tables created by this procedure.
  201. | See 'ReorderListToMatchDirectAccessTable()' to make the
  202. | order of items in a list conform to the order in a
  203. | cooresponding direct access table.
  204. |
  205. | EXAMPLE:  
  206. |           MyTable = BuildDirectAccessTableForList(MyList);
  207. | NOTE:  
  208. |
  209. | ASSUMES: Item pool has been set up.
  210. |          Sufficient memory exists to hold the table.
  211. |          At least one item exists in the given list.
  212. |
  213. | HISTORY: 09.12.89 by Lee Malone
  214. |          10.03.91 Revised for Focus.
  215. |                   Name changed from 
  216. |                   BuildARandomAccessTableForAList
  217. |          12.22.91 pointers to data rather than pointers
  218. |                   to items
  219. |          02.08.93 name changed from 
  220. |                   BuildALinearAccessTableForAList
  221. |          10.28.93 changed back to point to item records 
  222. |                   because mark field is part of data.
  223. |          11.21.93 name changed from 
  224. |                   BuildLinearAccessTableForList
  225. ------------------------------------------------------------*/
  226. AddressOfAddressOfItem
  227. BuildDirectAccessTableForList(AddressOfList AList)
  228. {
  229.     AddressOfAddressOfItem    Table;
  230.     Quad                    Entry;
  231.     Quad                    TableSize;
  232.  
  233.     PushTheListAndItem();
  234.     TheList = AList;
  235.     
  236.     TableSize = ((Quad) sizeof(AddressOfItem)) * TheItemCount;
  237.     
  238.     Table = (AddressOfAddressOfItem) AllocateMemory(TableSize);
  239.  
  240.     ToFirstItem();
  241.  
  242.     for( Entry = 0; Entry < TheItemCount; Entry++ )
  243.     {
  244.         Table[Entry] = TheItem;
  245.         ToNextItem();
  246.     }
  247.  
  248.     PullTheListAndItem();
  249.  
  250.     return(Table);
  251. }
  252.  
  253. /*------------------------------------------------------------
  254. | NAME: CleanUpTheListSystem
  255. |
  256. | PURPOSE: To reverse the action of SetUpTheListSystem.
  257. |
  258. | DESCRIPTION: 
  259. |
  260. | EXAMPLE:  CleanUpTheListSystem();
  261. |
  262. | NOTE: 
  263. |
  264. | ASSUMES: Any dynamic data attached to items has already
  265. |          been deallocated.
  266. |
  267. | HISTORY: 03.10.89 by Lee Malone
  268. |          07.10.89 upgraded to new structure
  269. |          07.28.89 added set up flag
  270. |          11.01.93 cleared the current list and item
  271. ------------------------------------------------------------*/
  272. Nothing
  273. CleanUpTheListSystem()
  274. {
  275.     if(!TheListSystemIsSetUp) return;
  276.     
  277.     TheListSystemIsSetUp--;
  278.     if( !TheListSystemIsSetUp )
  279.     {
  280.         FreeMemory( ListSpace );
  281.         FreeMemory( ItemSpace );
  282.  
  283.         TheList = 0;
  284.         TheItem = 0;
  285.         TheListStackIndex = 0;
  286.         MaxCountOfLists  = 0;
  287.         MaxCountOfItems  = 0;
  288.         ListSpace        = 0;
  289.         ItemSpace        = 0;
  290.         CountOfFreeItems = 0;
  291.         CountOfFreeLists = 0;
  292.         FirstFreeList    = 0;
  293.         FirstFreeItem    = 0;
  294.     }
  295. }
  296.  
  297. /*------------------------------------------------------------
  298. | NAME: CreateItem
  299. |
  300. | PURPOSE: To make a new empty, unmarked, non-inserted item.
  301. |
  302. | DESCRIPTION: 
  303. |
  304. | EXAMPLE:  AnItem = CreateItem();
  305. |
  306. | NOTE: 
  307. |
  308. | ASSUMES: 
  309. |
  310. | HISTORY: 01.04.89 by Lee Malone
  311. |          07.10.89 Revised for new item structure
  312. |          11.17.93 simplified logic
  313. |
  314. ------------------------------------------------------------*/
  315. AddressOfItem
  316. CreateItem()
  317. {
  318.     AddressOfItem AnItem;
  319.     
  320.     if(!IsItemCreationPossible())
  321.     {
  322.         printf("Error: Unable to CreateItem\n");
  323.         exit(1);
  324.     }
  325.     
  326.     CountOfFreeItems--;
  327.     AnItem = FirstFreeItem;
  328.     FirstFreeItem = GetNextItem(FirstFreeItem);
  329.     UnMarkItem(AnItem);
  330.     
  331.     return( AnItem );        
  332. }
  333.  
  334. /*------------------------------------------------------------
  335. | NAME: CreateItemForData
  336. |
  337. | PURPOSE: To make a new item and associate it with the given
  338. |          data.
  339. |
  340. | DESCRIPTION: Construction operation.
  341. |
  342. | EXAMPLE:  AnItem = CreateItemForData( "Existence exists." );
  343. |
  344. | NOTE: 
  345. |
  346. | ASSUMES: 
  347. |
  348. | HISTORY: 10.07.91 by Lee Malone
  349. |          10.29.93 ported from Focus 
  350. |
  351. ------------------------------------------------------------*/
  352. AddressOfItem
  353. CreateItemForData( AddressOfByte SomeData )
  354. {
  355.     AddressOfItem ThisItem;
  356.     
  357.     ThisItem = CreateItem();
  358.     PutItemDataAddress(ThisItem,SomeData);
  359.     return(ThisItem);
  360. }
  361.  
  362. /*------------------------------------------------------------
  363. | NAME: CreateList
  364. |
  365. | PURPOSE: To make a new empty, unmarked list.
  366. |
  367. | DESCRIPTION: 
  368. |
  369. | EXAMPLE:  AList = CreateList();
  370. |
  371. | NOTE: 
  372. |
  373. | ASSUMES: 
  374. |
  375. | HISTORY: 01.04.89 by Lee Malone
  376. |          07.10.89 new structure revision
  377. |          11.17.93 simplified logic
  378. |
  379. ------------------------------------------------------------*/
  380. AddressOfList
  381. CreateList()
  382. {
  383.     AddressOfList AList;
  384.     
  385.     if(!IsListCreationPossible())
  386.     {
  387.         printf("Error: Unable to Allocate List\n");
  388.         exit(1);
  389.     }
  390.     
  391.     CountOfFreeLists--;
  392.     AList = FirstFreeList;
  393.     FirstFreeList = 
  394.             (AddressOfList) GetFirstItemOfList(FirstFreeList);
  395.  
  396.     UnMarkList( AList );
  397.     MarkListAsEmpty( AList );
  398.     
  399.     return(AList);
  400. }
  401.  
  402. /*------------------------------------------------------------
  403. | NAME: DeleteAllReferencesToData
  404. |
  405. | PURPOSE: To delete all items from a list that refer to the
  406. |          given data address.
  407. |
  408. | DESCRIPTION:
  409. |
  410. | EXAMPLE:  DeleteAllReferencesToData( AList, SomeData);
  411. |
  412. | NOTE: 
  413. |
  414. | ASSUMES: 
  415. |
  416. | HISTORY: 01.14.89 by Lee Malone
  417. |          03.24.89 minor fixes
  418. |          10.28.93 name changed from 
  419. |                   'DeleteAllItemsThatMatchData'
  420. |          11.18.93 simplified logic
  421. ------------------------------------------------------------*/
  422. Nothing
  423. DeleteAllReferencesToData(AddressOfList AList,
  424.                           AddressOfByte SomeData)
  425. {
  426.     AddressOfItem AnItem;
  427.         
  428.     PushTheListAndItem();
  429.     TheList = AList;
  430.     ToFirstItem();
  431.     
  432.     while( TheItem )
  433.     {
  434.         if(TheDataAddress == SomeData)
  435.         {
  436.             AnItem = ExtractTheItem();
  437.                 
  438.             DeleteItem(AnItem);
  439.         }
  440.         else 
  441.         {
  442.             ToNextItem();
  443.         }
  444.     }
  445.     PullTheListAndItem();
  446. }
  447.  
  448. /*------------------------------------------------------------
  449. | NAME: DeleteFirstReferenceToData
  450. |
  451. | PURPOSE: To delete the first item in a list that refers to 
  452. |          the given data address.
  453. |
  454. | DESCRIPTION: Returns address of item that was deleted or
  455. | a '0' if no matching item was found.
  456. |
  457. | EXAMPLE:  DeleteFirstReferenceToData( AList, SomeData);
  458. |
  459. | NOTE: 
  460. |
  461. | ASSUMES: Data should not be freed using 'FreeMemory'.
  462. |
  463. | HISTORY: 12.12.91 by Lee Malone
  464. |          10.29.93 name changed from 
  465. |                   'ExtractFirstMatchingData'
  466. |           
  467. ------------------------------------------------------------*/
  468. AddressOfItem
  469. DeleteFirstReferenceToData(AddressOfList AList,
  470.                            AddressOfByte SomeData)
  471. {
  472.     AddressOfItem AnItem;
  473.     
  474.     AnItem = FindFirstItemLinkedToData( AList, SomeData); 
  475.                             
  476.     if( AnItem )
  477.     {
  478.         ExtractItemFromList(AList,AnItem);
  479.         DeleteItem(AnItem);
  480.     }
  481.     return(AnItem);
  482. }
  483.  
  484. /*------------------------------------------------------------
  485. | NAME: DeleteItem
  486. |
  487. | PURPOSE: To discard an item that isn't part of a list.
  488. |
  489. | DESCRIPTION: Before an item can be deleted it must first 
  490. | be extracted from the list that holds it. Returns memory 
  491. | allocated from the item pool.
  492. |
  493. | EXAMPLE:  DeleteItem(AnItem);
  494. |
  495. | NOTE: 
  496. |
  497. | ASSUMES: Item is not inserted in a list.
  498. |
  499. | HISTORY: 01.06.89 by Lee Malone
  500. |          07.10.89 new structure revision
  501. |
  502. ------------------------------------------------------------*/
  503. Nothing
  504. DeleteItem(AddressOfItem AnItem)
  505. {
  506.     CountOfFreeItems++;
  507.     PutNextItem(AnItem,FirstFreeItem);
  508.     FirstFreeItem = AnItem;
  509. }
  510.  
  511. /*------------------------------------------------------------
  512. | NAME: DeleteList
  513. |
  514. | PURPOSE: To delete items in a list and discard it.
  515. |
  516. | DESCRIPTION:
  517. |
  518. | EXAMPLE:  DeleteList(AList);
  519. |
  520. | NOTE: 
  521. |
  522. | ASSUMES: 
  523. |
  524. | HISTORY: 01.06.88 by Lee Malone
  525. |          11.17.93 incorporated 'ReturnListToListPool'.
  526. |
  527. ------------------------------------------------------------*/
  528. Nothing
  529. DeleteList(AddressOfList AList)
  530. {
  531.     AddressOfItem    AnItem;
  532.  
  533.     PushTheListAndItem();
  534.  
  535.     /* Make this the special list. */
  536.     TheList = AList;          
  537.  
  538.     /* Get rid of the items first. */
  539.     while(IsAnyItemsInList(TheList))  
  540.     {
  541.         ToFirstItem();
  542.  
  543.         AnItem = ExtractTheItem();
  544.  
  545.         DeleteItem(AnItem);
  546.     }
  547.     
  548.     /* Then add the list record to the free list. */
  549.     PutFirstItemOfList(AList,
  550.                        (AddressOfItem) FirstFreeList);
  551.     FirstFreeList = AList;
  552.     CountOfFreeLists++;
  553.  
  554.     PullTheListAndItem();
  555. }
  556.  
  557. /*------------------------------------------------------------
  558. | NAME: DeleteListOfDynamicData
  559. |
  560. | PURPOSE: To delete a list of items and their associated 
  561. |          dynamically allocated data.
  562. |
  563. | DESCRIPTION: If all of the data in the given list has been
  564. | created using 'AllocateMemory' then this procedure can be
  565. | used to free the list and data in a single procedure call.
  566. |
  567. | EXAMPLE:  DeleteListOfDynamicData(AList);
  568. |
  569. | NOTE: 
  570. |
  571. | ASSUMES: Every item data address points to a dynamicly 
  572. |          allocated segment of memory.
  573. |
  574. | HISTORY: 04.03.89 by Lee Malone
  575. |          10.23.89 removed tree capability
  576. |          10.03.91 Revised for Focus.
  577. |                   Name changed from
  578. |                   'DeleteListOfDynamicStrings'
  579. |          11.18.93 changed to call 'DeleteList'.
  580. ------------------------------------------------------------*/
  581. Nothing
  582. DeleteListOfDynamicData(AddressOfList AList)
  583. {
  584.     PushTheListAndItem();
  585.     
  586.     /* make this the implied list */
  587.     TheList = AList;
  588.     
  589.     ToFirstItem();
  590.     /* Free the data attached to each item. */
  591.     while(TheItem)    
  592.     {
  593.         /* free the dynamic data */
  594.         FreeMemory(TheDataAddress);                   
  595.         ToNextItem();
  596.     }
  597.  
  598.     /* Then free the list and item records. */
  599.     DeleteList(AList); 
  600.  
  601.     PullTheListAndItem();
  602. }
  603.  
  604. /*------------------------------------------------------------
  605. | NAME: DeleteMarkedItems
  606. |
  607. | PURPOSE: To delete all of the marked items in a list.
  608. |
  609. | DESCRIPTION: 
  610. |
  611. | EXAMPLE:  DeleteMarkedItems(AList);
  612. |
  613. | NOTE:  
  614. |
  615. | ASSUMES: Data attached to item doesn't need to be 
  616. |          deallocated.
  617. |
  618. | HISTORY: 11.04.93 by Lee Malone
  619. ------------------------------------------------------------*/
  620. Nothing
  621. DeleteMarkedItems(AddressOfList AList)
  622. {
  623.     DeleteList( ExtractMarkedItems(AList) );
  624. }
  625.  
  626. /*------------------------------------------------------------
  627. | NAME: DuplicateList
  628. |
  629. | PURPOSE: To duplicate a list.  
  630. |
  631. | DESCRIPTION: Creates a new list of item records pointing to 
  632. | the same data as the given list.
  633. |
  634. | This is useful when it is desirable to access the same data 
  635. | but in different orders or select different sets of data
  636. | from the list using the marking bits in the mark field.
  637. |
  638. | EXAMPLE:  DupList = DuplicateList(AList);
  639. |
  640. | NOTE: Does NOT duplicate the data associated with the item
  641. |       records.
  642. |
  643. | ASSUMES: 
  644. |
  645. | HISTORY: 01.13.89 by Lee Malone
  646. |          07.11.89 Added data type, mark and name copy
  647. |          02.08.93 removed item count control in favor of 
  648. |                   TheItem being non-0.
  649. |
  650. ------------------------------------------------------------*/
  651. AddressOfList
  652. DuplicateList(AddressOfList AList)
  653. {
  654.     AddressOfList DuplicateListAddress;
  655.     AddressOfItem NewItem;
  656.  
  657.     PushTheListAndItem();
  658.     
  659.     DuplicateListAddress = CreateList();
  660.     
  661.     if(IsAnyItemsInList(AList))
  662.     {
  663.         TheList = AList;
  664.         
  665.         ToFirstItem();
  666.         
  667.         while(TheItem)
  668.         {
  669.             NewItem = CreateItemForData(TheDataAddress);
  670.             PutItemMark(NewItem, TheItemMark);
  671.             InsertItemLastInList(DuplicateListAddress,NewItem);
  672.             ToNextItem();
  673.         }
  674.     }
  675.     
  676.     PullTheListAndItem();
  677.  
  678.     return(DuplicateListAddress);
  679. }
  680.  
  681. /*------------------------------------------------------------
  682. | NAME: DuplicateMarkedItems
  683. |
  684. | PURPOSE: To duplicate the marked items of a list.  
  685. |
  686. | DESCRIPTION: Creates a new list of item records pointing to 
  687. | the same data as the marked items in the given list.
  688. |
  689. | This is useful when it is desirable to access the same data 
  690. | but in different orders or select different sets of data
  691. | from the list using the marking bits in the mark field.
  692. |
  693. | EXAMPLE:  DupList = DuplicateMarkedItems(AList);
  694. |
  695. | NOTE: Does NOT duplicate the data associated with the item
  696. |       records.
  697. |
  698. | ASSUMES: 
  699. |
  700. | HISTORY: 11.04.93 by Lee Malone
  701. |          11.19.93 simplified logic
  702. |
  703. ------------------------------------------------------------*/
  704. AddressOfList
  705. DuplicateMarkedItems(AddressOfList AList)
  706. {
  707.     AddressOfList TheDuplicateList;
  708.     AddressOfItem NewItem;
  709.  
  710.     TheDuplicateList = CreateList();
  711.  
  712.     if(!IsAnyItemsInList(AList)) return(TheDuplicateList);
  713.     
  714.     PushTheListAndItem();
  715.     
  716.     TheList = AList;
  717.         
  718.     ToFirstItem();
  719.         
  720.     while(TheItem)
  721.     {
  722.         if(IsItemMarked(TheItem))
  723.         {
  724.             NewItem = CreateItemForData(TheDataAddress);
  725.             PutItemMark(NewItem, TheItemMark);
  726.             InsertItemLastInList(TheDuplicateList,NewItem);
  727.         }
  728.         ToNextItem();
  729.     }
  730.     
  731.     PullTheListAndItem();
  732.  
  733.     return(TheDuplicateList);
  734. }
  735.  
  736. /*------------------------------------------------------------
  737. | NAME: ExchangeItems
  738. |
  739. | PURPOSE: To exchange any two adjacent items in a given list.
  740. |
  741. | DESCRIPTION:
  742. |
  743. | EXAMPLE:  ExchangeItems(AList, AItem, BItem);
  744. |
  745. | NOTE: 
  746. |
  747. | ASSUMES: Both items are valid item record addresses.
  748. |          The items are next to one another.
  749. |
  750. | HISTORY: 01.09.89 by Lee Malone
  751. |          07.10.89 revised to include type exchange
  752. |          07.11.89 revised to include name and mark exchange
  753. |          07.19.89 revised to exchange items, not just the 
  754. |                   data (latent error)
  755. |
  756. ------------------------------------------------------------*/
  757. Nothing
  758. ExchangeItems(AddressOfList AList,
  759.               AddressOfItem AItem,
  760.               AddressOfItem BItem)
  761. {
  762.     AddressOfItem   WItem, XItem, YItem, ZItem;
  763.  
  764.     XItem = AItem;
  765.     YItem = BItem;
  766.  
  767.     if( GetNextItem(XItem) != YItem )
  768.     {
  769.         XItem = BItem;
  770.         YItem = AItem;
  771.     }
  772.  
  773.     WItem = GetPriorItem(XItem);
  774.     ZItem = GetNextItem(YItem);
  775.  
  776.     PutPriorItem(XItem,YItem);
  777.     PutNextItem(YItem,XItem);
  778.     PutPriorItem(YItem,WItem);
  779.     PutNextItem(XItem,ZItem);
  780.  
  781.     if( WItem == 0 )             /* XItem was first */
  782.     {
  783.         PutFirstItemOfList(AList,YItem);
  784.     }
  785.     else
  786.     {
  787.         PutNextItem(WItem,YItem);
  788.     }
  789.  
  790.     if( ZItem == 0 )             /* YItem was last */
  791.     {
  792.         PutLastItemOfList(AList,XItem);
  793.     }
  794.     else
  795.     {
  796.         PutPriorItem(ZItem,XItem);
  797.     }
  798. }
  799.  
  800. /*------------------------------------------------------------
  801. | NAME: ExtractFirstItemFromList
  802. |
  803. | PURPOSE: To extract the first item from a list. 
  804. |
  805. | DESCRIPTION:
  806. |
  807. | EXAMPLE:  AnItem = ExtractFirstItemFromList(AList);
  808. |
  809. | NOTE: 
  810. |
  811. | ASSUMES: 
  812. |
  813. | HISTORY: 01.06.88 by Lee Malone
  814. |          07.10.89 simplified
  815. |
  816. ------------------------------------------------------------*/
  817. AddressOfItem
  818. ExtractFirstItemFromList(AddressOfList AList)
  819. {
  820.     return( 
  821.         ExtractItemFromList(AList, GetFirstItemOfList(AList)) 
  822.     );
  823. }
  824.  
  825. /*------------------------------------------------------------
  826. | NAME: ExtractItemFromList
  827. |
  828. | PURPOSE: To extract an item from a list.
  829. |
  830. | DESCRIPTION:
  831. |
  832. | EXAMPLE:  AnItem = ExtractItemFromList(AList, AnItem);
  833. |
  834. | NOTE: 
  835. |
  836. | ASSUMES: 
  837. |
  838. | HISTORY: 01.06.88 by Lee Malone
  839. |
  840. ------------------------------------------------------------*/
  841. AddressOfItem
  842. ExtractItemFromList(AddressOfList AList, 
  843.                     AddressOfItem AnItem)
  844. {
  845.     if( AnItem )
  846.     {    
  847.         PushTheListAndItem();
  848.     
  849.         TheList = AList;
  850.         TheItem = AnItem;
  851.         
  852.         AnItem = ExtractTheItem();
  853.     
  854.         PullTheListAndItem();
  855.     }
  856.     return(AnItem);
  857. }
  858.  
  859. /*------------------------------------------------------------
  860. | NAME: ExtractLastItemFromList
  861. |
  862. | PURPOSE: To extract the last item from a list.
  863. |
  864. | DESCRIPTION:
  865. |
  866. | EXAMPLE: AnItem = ExtractLastItemFromList(AList); 
  867. |
  868. | NOTE: 
  869. |
  870. | ASSUMES: 
  871. |
  872. | HISTORY: 01.09.88 by Lee Malone
  873. |          07.10.89 simplified
  874. |
  875. ------------------------------------------------------------*/
  876. AddressOfItem
  877. ExtractLastItemFromList(AddressOfList AList)
  878. {
  879.     return( 
  880.         ExtractItemFromList(AList, GetLastItemOfList(AList)) 
  881.     );
  882. }
  883.  
  884. /*------------------------------------------------------------
  885. | NAME: ExtractMarkedItems
  886. |
  887. | PURPOSE: To extract all marked items from a list and return
  888. |          a list of those items.
  889. |
  890. | DESCRIPTION:
  891. |
  892. | EXAMPLE:  MarkedList = ExtractMarkedItems(AList);
  893. |
  894. | NOTE: 
  895. |
  896. | ASSUMES: 
  897. |
  898. | HISTORY: 11.04.93 by Lee Malone
  899. |          11.19.93 simplified logic
  900. ------------------------------------------------------------*/
  901. AddressOfList
  902. ExtractMarkedItems(AddressOfList AList)
  903. {
  904.     AddressOfItem    AnItem;
  905.     AddressOfList    ResultList;
  906.         
  907.     ResultList = CreateList();
  908.  
  909.     if(!IsAnyItemsInList(AList)) return(ResultList);
  910.  
  911.     PushTheListAndItem();
  912.     
  913.     TheList = AList;
  914.     
  915.     ToFirstItem();
  916.     
  917.     do
  918.     {
  919.         if(IsItemMarked(TheItem))
  920.         {
  921.             AnItem = ExtractTheItem();
  922.             InsertItemLastInList(ResultList, AnItem);
  923.         }
  924.         else
  925.         {
  926.             ToNextItem();
  927.         }
  928.     }
  929.     while( TheItem );
  930.     
  931.     PullTheListAndItem();
  932.     
  933.     return(ResultList);
  934. }
  935.  
  936. /*------------------------------------------------------------
  937. | NAME: ExtractTheItem
  938. |
  939. | PURPOSE: To extract the current item from the current list.
  940. |
  941. | DESCRIPTION:
  942. |
  943. | EXAMPLE:  AnItem = ExtractTheItem();
  944. |
  945. | NOTE: 
  946. |
  947. | ASSUMES: Direction through list is first-to-last.
  948. |
  949. | HISTORY: 01.06.88 by Lee Malone
  950. |          09.07.89 added 0 item protection
  951. |          10.04.91 Revised for Focus.
  952. |          11.26.91 revised to reset TheItem
  953. |          12.01.91 IsItemAlone TheItem reset
  954. |          10.25.93 removed MarkItemAsNotInserted
  955. |          10.28.93 upgrade from Focus
  956. |
  957. ------------------------------------------------------------*/
  958. AddressOfItem
  959. ExtractTheItem()
  960. {
  961.     AddressOfItem PrvItem;
  962.     AddressOfItem NxtItem;
  963.     AddressOfItem XItem;
  964.     
  965.     XItem = TheItem; /* The item being extracted */
  966.  
  967.     if(TheItem == 0) return(XItem);
  968.     
  969.     PrvItem = ThePriorItem;
  970.     NxtItem = TheNextItem;
  971.     
  972.     TheItemCount--;
  973.     
  974.     if(IsItemAlone(TheItem))
  975.     {
  976.         MarkListAsEmpty(TheList);
  977.         TheItem = 0;
  978.     }
  979.     else
  980.     {
  981.         if(IsItemFirst(TheItem))
  982.         {
  983.             /* mark next item as first  */
  984.             MarkItemAsFirst(NxtItem);   
  985.             TheFirstItem = NxtItem;     
  986.             /* list now points to next item */
  987.             ToFirstItem(); /* Reset TheItem */
  988.         }
  989.         else /* not the first item */
  990.         {
  991.             if(IsItemLast(TheItem))
  992.             {
  993.                 /* mark previous item as last */
  994.                 MarkItemAsLast(PrvItem); 
  995.                 TheLastItem = PrvItem;   
  996.                 /* list now points to previous item */
  997.                 ToLastItem(); /* reset TheItem */
  998.             }
  999.             else /* somewhere in the middle */
  1000.             {
  1001.                 /* relink neighboring items together */
  1002.                 PutPriorItem(NxtItem,PrvItem);
  1003.                 PutNextItem(PrvItem,NxtItem);
  1004.                 TheItem = PrvItem; /* reset TheItem */
  1005.             }
  1006.                 
  1007.         }
  1008.     }
  1009.     return(XItem);
  1010. }
  1011.  
  1012. /*------------------------------------------------------------
  1013. | NAME: FindFirstItemLinkedToData
  1014. |
  1015. | PURPOSE: To find the first item in a list pointing to the 
  1016. | given data address.
  1017. |
  1018. | DESCRIPTION: Returns address of the item found, else 0.
  1019. |
  1020. | EXAMPLE:  
  1021. |
  1022. |     AnItem = FindFirstItemLinkedToData(AList,SomeData);
  1023. |
  1024. | NOTE: 
  1025. |
  1026. | ASSUMES: 
  1027. |
  1028. | HISTORY: 12.12.91 by Lee Malone
  1029. |          10.29.93 ported from procedure in Focus named,
  1030. |                     'FindFirstNodeMatchingData'
  1031. |          11.18.93 simplified logic
  1032. ------------------------------------------------------------*/
  1033. AddressOfItem
  1034. FindFirstItemLinkedToData( AddressOfList AList, 
  1035.                            AddressOfByte SomeData )
  1036. {
  1037.      AddressOfItem    Result;
  1038.  
  1039.     Result = (AddressOfItem) 0;
  1040.  
  1041.     /* Return if no items in the list. */
  1042.     if( !IsAnyItemsInList(AList) ) return(Result);
  1043.     
  1044.     PushTheListAndItem();
  1045.  
  1046.     TheList = AList;
  1047.  
  1048.     ToFirstItem();
  1049.  
  1050.     while( !IsItemLast(TheItem) )
  1051.     {
  1052.         if(TheDataAddress == SomeData) break;
  1053.  
  1054.         ToNextItem();
  1055.     }
  1056.  
  1057.     if( TheDataAddress == SomeData )
  1058.     {
  1059.         Result = TheItem;
  1060.      }
  1061.  
  1062.     PullTheListAndItem();
  1063.  
  1064.     return( Result );
  1065. }
  1066.  
  1067. /*------------------------------------------------------------
  1068. | NAME: FindFirstMarkedItem
  1069. |
  1070. | PURPOSE: To find the address of the first marked item in a 
  1071. | list.
  1072. |
  1073. | DESCRIPTION:  Returns address of marked item or 0 if no
  1074. |               marked item was found.
  1075. |
  1076. | EXAMPLE:  AnItem = FindFirstMarkedItem(AList);
  1077. |
  1078. | NOTE:  
  1079. |
  1080. | ASSUMES: 
  1081. |
  1082. | HISTORY: 12.18.91 by Lee Malone
  1083. |          02.08.93 converted from list.txt
  1084. |          11.18.93 simplified logic
  1085. ------------------------------------------------------------*/
  1086. AddressOfItem
  1087. FindFirstMarkedItem(AddressOfList AList)
  1088. {
  1089.     AddressOfItem    MarkedItem;
  1090.     
  1091.     PushTheListAndItem();
  1092.     
  1093.     TheList = AList;
  1094.     MarkedItem = (AddressOfItem) 0;
  1095.     
  1096.     ToFirstItem();
  1097.     
  1098.     while(TheItem)
  1099.     {
  1100.         if( IsItemMarked(TheItem) )
  1101.         {
  1102.             MarkedItem = TheItem;
  1103.             break;
  1104.         }
  1105.         ToNextItem();
  1106.     }
  1107.  
  1108.     PullTheListAndItem();
  1109.     
  1110.     return(MarkedItem);
  1111. }
  1112.  
  1113. /*------------------------------------------------------------
  1114. | NAME: FindFirstMatchingItem
  1115. |
  1116. | PURPOSE: To FindFirstMatchingItem.
  1117. |
  1118. | DESCRIPTION: Returns pointer to the item found, else 0
  1119. | Expects data field offset, width and address of value to 
  1120. | match.
  1121. |
  1122. | EXAMPLE:
  1123. |  
  1124. |  SearchValue          = (AddressOfByte) "John Galt";
  1125. |  SearchKeyFieldOffset = 0;
  1126. |  SearchFieldWidth        = CountString(SearchPattern);
  1127. |
  1128. |  MatchingItem = FindFirstMatchingItem( NameList, 
  1129. |                                         SearchKeyFieldOffset, 
  1130. |                                         SearchFieldWidth, 
  1131. |                                         SearchValue );
  1132. |
  1133. | NOTE: 
  1134. |
  1135. | ASSUMES: 
  1136. |
  1137. | HISTORY: 10.23.89 by Lee Malone
  1138. |          11.18.93 simplified logic
  1139. |
  1140. ------------------------------------------------------------*/
  1141. AddressOfItem
  1142. FindFirstMatchingItem( AddressOfList AList, 
  1143.                        Pair          FieldOffset, 
  1144.                        Pair             FieldWidth, 
  1145.                        AddressOfByte SearchValue )
  1146. {
  1147.      AddressOfItem    Result;
  1148.  
  1149.     Result = (AddressOfItem) 0;
  1150.  
  1151.     /* Return if no items in the list. */
  1152.     if( !IsAnyItemsInList(AList) ) return(Result);
  1153.  
  1154.     PushTheListAndItem();
  1155.  
  1156.     TheList = AList;
  1157.  
  1158.     ToFirstItem();
  1159.  
  1160.     while( !IsItemLast(TheItem)  )
  1161.     {
  1162.         if(IsTheDataMatching(FieldOffset, FieldWidth, SearchValue))
  1163.             break;
  1164.         ToNextItem();
  1165.     }
  1166.  
  1167.     if( IsTheDataMatching(FieldOffset, FieldWidth, SearchValue) )
  1168.     {
  1169.         Result = TheItem;
  1170.      }
  1171.  
  1172.     PullTheListAndItem();
  1173.  
  1174.     return( Result );
  1175. }
  1176.  
  1177. /*------------------------------------------------------------
  1178. | NAME: FindFirstUnMarkedItem
  1179. |
  1180. | PURPOSE: To get the address of the first unmarked item in a 
  1181. |          list.
  1182. |
  1183. | DESCRIPTION: Returns address of unmarked item or 0 if none
  1184. |              found.
  1185. |
  1186. | EXAMPLE:  AnItem = FindFirstUnMarkedItem(AList);
  1187. |
  1188. | NOTE:  
  1189. |
  1190. | ASSUMES: 
  1191. |
  1192. | HISTORY: 12.11.91 by Lee Malone
  1193. |          12.14.91 error: loop termination flag not dropped
  1194. |          02.08.93 converted from FindFirstUnMarkedItem in 
  1195. |                   list.txt
  1196. |          11.19.93 simplified logic
  1197. ------------------------------------------------------------*/
  1198. AddressOfItem
  1199. FindFirstUnMarkedItem(AddressOfList AList)
  1200. {
  1201.     AddressOfItem    UnMarkedItem;
  1202.     
  1203.     PushTheListAndItem();
  1204.     
  1205.     TheList = AList;
  1206.     UnMarkedItem = (AddressOfItem) 0;
  1207.  
  1208.     ToFirstItem();
  1209.     
  1210.     while(TheItem)
  1211.     {
  1212.         if( !IsItemMarked(TheItem) )
  1213.         {
  1214.             UnMarkedItem = TheItem;
  1215.             break;
  1216.         }
  1217.         ToNextItem();
  1218.     }
  1219.  
  1220.     PullTheListAndItem();
  1221.     
  1222.     return(UnMarkedItem);
  1223. }
  1224.  
  1225. /*------------------------------------------------------------
  1226. | NAME: FindIndexOfFirstMarkedItem
  1227. |
  1228. | PURPOSE: To get the item index of the first marked item in 
  1229. | a list.
  1230. |
  1231. | DESCRIPTION: The first item of the list has an index of 0,
  1232. | the next one is 1 and so on.
  1233. |
  1234. | EXAMPLE:  ItemIndex = FindIndexOfFirstMarkedItem(AList);
  1235. |
  1236. | NOTE:  
  1237. |
  1238. | ASSUMES: At least one item is marked in the list.
  1239. |
  1240. | HISTORY: 10.18.91 by Lee Malone
  1241. |          02.08.93 converted from list.txt
  1242. ------------------------------------------------------------*/
  1243. Quad
  1244. FindIndexOfFirstMarkedItem(AddressOfList AList)
  1245. {
  1246.     Quad    IndexOfMarkedItem;
  1247.     
  1248.     PushTheListAndItem();
  1249.     
  1250.     TheList = AList;
  1251.     
  1252.     ToFirstItem();
  1253.     
  1254.     IndexOfMarkedItem = 0;
  1255.  
  1256.     while(!IsItemMarked(TheItem))
  1257.     {
  1258.         IndexOfMarkedItem++;
  1259.         ToNextItem();
  1260.     }
  1261.  
  1262.     PullTheListAndItem();
  1263.     return(IndexOfMarkedItem);
  1264. }
  1265.  
  1266. /*------------------------------------------------------------
  1267. | NAME: FindNextMatchingItem
  1268. |
  1269. | PURPOSE: To find the next item in a list matching the search 
  1270. |          string.
  1271. |
  1272. | DESCRIPTION: Returns pointer to the item found, else 0
  1273. | Expects starting item, data field offset, width and pointer 
  1274. | to value to match. Starts testing for a match on the item 
  1275. | AFTER the one supplied.
  1276. |
  1277. |     To be used in conjunction with "FindFirstMatchingItem".
  1278. |
  1279. | EXAMPLE:  
  1280. |
  1281. |  SearchValue          = (AddressOfByte) "John Galt";
  1282. |  SearchKeyFieldOffset = 0;
  1283. |  SearchFieldWidth        = CountString(SearchPattern);
  1284. |
  1285. |  MatchingItem = FindFirstMatchingItem( NameList, 
  1286. |                                         SearchKeyFieldOffset, 
  1287. |                                         SearchFieldWidth, 
  1288. |                                         SearchValue );
  1289. |
  1290. |  NextMatchItem = FindNextMatchingItem( NameList, 
  1291. |                                        MatchingItem,
  1292. |                                         SearchKeyFieldOffset, 
  1293. |                                         SearchFieldWidth, 
  1294. |                                         SearchValue );
  1295. |
  1296. | NOTE: 
  1297. |
  1298. | ASSUMES: 
  1299. |
  1300. | HISTORY: 10.23.89 by Lee Malone
  1301. |
  1302. ------------------------------------------------------------*/
  1303. AddressOfItem
  1304. FindNextMatchingItem( AddressOfList AList, 
  1305.                       AddressOfItem AnItem, 
  1306.                       Pair             FieldOffset, 
  1307.                       Pair            FieldWidth, 
  1308.                       AddressOfByte SearchValue )
  1309. {
  1310.      AddressOfItem    Result;
  1311.  
  1312.     Result = 0;
  1313.  
  1314.     /* Return if no items in the list. */
  1315.     if( !IsAnyItemsInList(AList) ) return(Result);
  1316.     
  1317.     PushTheListAndItem();
  1318.  
  1319.     TheList = AList;
  1320.     TheItem = AnItem;
  1321.  
  1322.     ToNextItem();
  1323.  
  1324.     while( !IsItemLast(TheItem)  )
  1325.     {
  1326.         if(IsTheDataMatching(FieldOffset, FieldWidth, SearchValue))
  1327.             break;
  1328.         ToNextItem();
  1329.     }
  1330.  
  1331.     if( IsTheDataMatching(FieldOffset, FieldWidth, SearchValue) )
  1332.     {
  1333.         Result = TheItem;
  1334.      }
  1335.  
  1336.     PullTheListAndItem();
  1337.  
  1338.     return( Result );
  1339. }
  1340.  
  1341. /*------------------------------------------------------------
  1342. | NAME: FindPlaceInOrderedList
  1343. |
  1344. | PURPOSE: To find the item before which the data is to be 
  1345. |          inserted (data = or < the insertion item's data).
  1346. |
  1347. | DESCRIPTION: Returns pointer to the item found, else 0 if
  1348. | item should be appended to the end of the list.
  1349. |
  1350. | EXAMPLE: AnItem = FindPlaceInOrderedList(NameList,
  1351. |                       (AddressOfByte) "Ken Dannager", 
  1352. |                       CompareStrings); 
  1353. |
  1354. | NOTE: 
  1355. |
  1356. | ASSUMES: 
  1357. |
  1358. | HISTORY: 09.06.89 by Lee Malone
  1359. |          11.21.93 simplified logic
  1360. |
  1361. ------------------------------------------------------------*/
  1362. AddressOfItem
  1363. FindPlaceInOrderedList( AddressOfList AList, 
  1364.                         AddressOfByte SomeData, 
  1365.     AddressOfComparisonProcedure ComparisonProcedure )
  1366. {
  1367.     AddressOfItem    AnItem;
  1368.     Comparison        Result;
  1369.  
  1370.     AnItem = (AddressOfItem) 0;
  1371.  
  1372.     if(!IsAnyItemsInList(AList)) return(AnItem);
  1373.     
  1374.     PushTheListAndItem();
  1375.  
  1376.     TheList = AList;
  1377.     ToFirstItem();
  1378.  
  1379.     while(TheItem)
  1380.     {
  1381.         Result = (*ComparisonProcedure) 
  1382.                     (TheDataAddress, SomeData);
  1383.                     
  1384.         /* 
  1385.          * If the current item is of higher order than 
  1386.          * the data supplied then exit the loop.
  1387.          */
  1388.         if(Result > 0) break;
  1389.         
  1390.         ToNextItem();
  1391.     }
  1392.     
  1393.     AnItem = TheItem;
  1394.     
  1395.     PullTheListAndItem();
  1396.     
  1397.     return(AnItem);
  1398. }
  1399.  
  1400. /*------------------------------------------------------------
  1401. | NAME: FindPlaceInOrderedDirectAccessTable
  1402. |
  1403. | PURPOSE: To find the entry holding the address of the item 
  1404. |          before which the data is to be inserted; data = or 
  1405. |          < the insertion item's data.
  1406. |
  1407. | DESCRIPTION: Returns address of the table entry found, 
  1408. |              else 0 if it should be appended to the end
  1409. |              of the table.
  1410. |
  1411. | EXAMPLE: AnItemEntry = 
  1412. |            FindPlaceInOrderedDirectAccessTable(
  1413. |                       NameTable,
  1414. |                       CountOfNamesInTable,
  1415. |                       (AddressOfByte) "Ken Dannager", 
  1416. |                       CompareStrings); 
  1417. |
  1418. | NOTE: Uses fast binary search algorithm.
  1419. |
  1420. | ASSUMES: 
  1421. |
  1422. | HISTORY: 09.14.89 by Lee Malone
  1423. |          11.21.93 simplified logic
  1424. |
  1425. ------------------------------------------------------------*/
  1426. AddressOfAddressOfItem
  1427. FindPlaceInOrderedDirectAccessTable( 
  1428.     AddressOfAddressOfItem       ATable, 
  1429.     Quad                         ACount, 
  1430.     AddressOfByte                SomeData, 
  1431.     AddressOfComparisonProcedure ComparisonProcedure )
  1432. {
  1433.     AddressOfAddressOfItem    Result;
  1434.     SignedQuad                Hi, Lo, Mid; 
  1435.     Comparison                Cond;
  1436.  
  1437.     Result = 0;
  1438.  
  1439.     if(ACount <= 0) return(Result);
  1440.     
  1441.     /* binary search; ATable[] must be in ascending order */
  1442.     Lo = 0;  
  1443.     Hi = (SignedQuad) ACount - 1;
  1444.  
  1445.     while( Lo <= Hi )
  1446.     {
  1447.         Mid = (Hi + Lo) >> 1; /* (Hi+Lo)/2 */
  1448.  
  1449.         Cond = (*ComparisonProcedure)
  1450.                   (SomeData, GetItemDataAddress(ATable[Mid]) );
  1451.  
  1452.         if( Cond == 0 )
  1453.         {    
  1454.             Result = &ATable[Mid];  /* exact match */
  1455.             return(Result);
  1456.         }
  1457.  
  1458.         if( Cond < 0 ) 
  1459.         {
  1460.             Hi = Mid - 1;
  1461.         }
  1462.         else
  1463.         {
  1464.             Lo = Mid + 1;
  1465.         }
  1466.     }
  1467.     
  1468.     if( Lo == ACount ) return(Result); /* beyond table */
  1469.     
  1470.     Result = &ATable[Lo];        /* higher order entry */
  1471.  
  1472.     return(Result);
  1473. }
  1474.  
  1475. /*------------------------------------------------------------
  1476. | NAME: InsertDataAfterItemInList
  1477. |
  1478. | PURPOSE: To insert a data address into a new item that is 
  1479. | inserted after a item in a list.
  1480. |
  1481. | DESCRIPTION:
  1482. |
  1483. | EXAMPLE:  AnItem = InsertDataAfterItemInList(AList,
  1484. |                                              ItemBefore,
  1485. |                                              DataToInsert);
  1486. |
  1487. | NOTE: 
  1488. |
  1489. | ASSUMES: 
  1490. |
  1491. | NOTE: Returns address of the created item.
  1492. |
  1493. | HISTORY:    01.09.88 by Lee Malone
  1494. |
  1495. ------------------------------------------------------------*/
  1496. AddressOfItem
  1497. InsertDataAfterItemInList(AddressOfList AList,
  1498.                           AddressOfItem AnItem,
  1499.                           AddressOfByte AddressOfData)
  1500. {
  1501.     AddressOfItem NewItem;
  1502.     
  1503.     NewItem = CreateItemForData(AddressOfData);
  1504.     InsertItemAfterItemInList(AList,AnItem,NewItem);
  1505.     return(NewItem);
  1506. }
  1507.  
  1508. /*------------------------------------------------------------
  1509. | NAME: InsertDataBeforeItemInList
  1510. |
  1511. | PURPOSE: To insert a data address into a new item that is 
  1512. | inserted before a item in a list.
  1513. |
  1514. | DESCRIPTION:
  1515. |
  1516. | EXAMPLE:  AnItem = InsertDataBeforeItemInList(AList,
  1517. |                                              ItemAfter,
  1518. |                                              DataToInsert);
  1519. |
  1520. | NOTE: 
  1521. |
  1522. | ASSUMES: 
  1523. |
  1524. | NOTE: Returns address of the created item.
  1525. |
  1526. | HISTORY:    01.09.88 by Lee Malone
  1527. |
  1528. ------------------------------------------------------------*/
  1529. AddressOfItem
  1530. InsertDataBeforeItemInList(AddressOfList AList,
  1531.                            AddressOfItem AnItem,
  1532.                            AddressOfByte AddressOfData)
  1533. {
  1534.     AddressOfItem NewItem;
  1535.     
  1536.     NewItem = CreateItemForData(AddressOfData);
  1537.     InsertItemBeforeItemInList(AList,AnItem,NewItem);
  1538.     return(NewItem);
  1539. }
  1540.  
  1541. /*------------------------------------------------------------
  1542. | NAME: InsertDataFirstInList
  1543. |
  1544. | PURPOSE: To insert the given data address into a new item 
  1545. | that is inserted first in a list.
  1546. |
  1547. | DESCRIPTION:
  1548. |
  1549. | EXAMPLE:  AnItem = InsertDataFirstInList(AList,
  1550. |                                          DataToInsert);
  1551. |
  1552. | NOTE: 
  1553. |
  1554. | ASSUMES: 
  1555. |
  1556. | NOTE: Returns address of the created item.
  1557. |
  1558. | HISTORY:    01.06.88 by Lee Malone
  1559. |
  1560. ------------------------------------------------------------*/
  1561. AddressOfItem
  1562. InsertDataFirstInList(AddressOfList AList,
  1563.                       AddressOfByte DataToInsert)
  1564. {
  1565.     AddressOfItem AnItem;
  1566.     
  1567.     AnItem = CreateItemForData(DataToInsert);
  1568.     InsertItemFirstInList(AList,AnItem);
  1569.     return(AnItem);
  1570. }
  1571.  
  1572. /*------------------------------------------------------------
  1573. | NAME: InsertDataInOrderedList
  1574. |
  1575. | PURPOSE: To insert the given data into an ordered list.
  1576. |
  1577. | DESCRIPTION: The given comparison procedure is the same
  1578. | one used to sort the list in order.
  1579. |
  1580. | EXAMPLE:  NewItem = InsertDataInOrderedList( 
  1581. |                            NameList,
  1582. |                            "Francisco d'Anconia",
  1583. |                            CompareStrings);
  1584. |
  1585. | NOTE: 
  1586. |
  1587. | ASSUMES: 
  1588. |
  1589. | NOTE: Returns address of the created item.
  1590. |
  1591. | HISTORY: 09.06.89 by Lee Malone
  1592. |
  1593. ------------------------------------------------------------*/
  1594. AddressOfItem
  1595. InsertDataInOrderedList(AddressOfList AList,
  1596.                         AddressOfByte SomeData,
  1597.     AddressOfComparisonProcedure ComparisonProcedure)
  1598. {
  1599.     AddressOfItem     AnItem;
  1600.     AddressOfItem    InsertionItem;
  1601.  
  1602.  
  1603.     InsertionItem  = FindPlaceInOrderedList( 
  1604.                         AList, 
  1605.                         SomeData, 
  1606.                         ComparisonProcedure );
  1607.  
  1608.     AnItem = InsertDataBeforeItemInList( 
  1609.                         AList, 
  1610.                         InsertionItem, 
  1611.                         SomeData );
  1612.  
  1613.     return( AnItem );
  1614. }
  1615.  
  1616. /*------------------------------------------------------------
  1617. | NAME: InsertDataLastInList
  1618. |
  1619. | PURPOSE: To insert the given data address into a new item 
  1620. | that is inserted last in a list.
  1621. |
  1622. | DESCRIPTION:
  1623. |
  1624. | EXAMPLE:  NewItem = InsertDataLasInList(AList, SomeData);
  1625. |
  1626. | NOTE: 
  1627. |
  1628. | ASSUMES: 
  1629. |
  1630. | NOTE: Returns address of the created item.
  1631. |
  1632. | HISTORY: 01.09.88 by Lee Malone
  1633. |
  1634. ------------------------------------------------------------*/
  1635. AddressOfItem
  1636. InsertDataLastInList(AddressOfList AList,
  1637.                      AddressOfByte SomeData)
  1638. {
  1639.     AddressOfItem AnItem;
  1640.     
  1641.     AnItem = CreateItemForData(SomeData);
  1642.     InsertItemLastInList(AList,AnItem);
  1643.  
  1644.     return(AnItem);
  1645. }
  1646.  
  1647. /*------------------------------------------------------------
  1648. | NAME: InsertItemAfterItemInList
  1649. |
  1650. | PURPOSE: To insert an item after another item in a list.
  1651. |
  1652. | DESCRIPTION: If the item to preceed the one being inserted
  1653. | is '0', then insert the item as first in the list.
  1654. |
  1655. |
  1656. | EXAMPLE:  InsertItemAfterItemInList(AList, ItemBefore,
  1657. |                                      ItemToInsert);
  1658. |
  1659. | NOTE: 
  1660. |
  1661. | ASSUMES: 
  1662. |
  1663. | HISTORY: 01.09.88 by Lee Malone
  1664. |          11.21.93 if 'ItemBefore' == 0 condition added
  1665. |
  1666. ------------------------------------------------------------*/
  1667. Nothing
  1668. InsertItemAfterItemInList(AddressOfList AList,
  1669.                           AddressOfItem ItemBefore,
  1670.                           AddressOfItem ItemToInsert)
  1671. {
  1672.     AddressOfItem NextItem;
  1673.     
  1674.     if(!ItemBefore) 
  1675.     {
  1676.         InsertItemFirstInList(AList,ItemToInsert);
  1677.         return;
  1678.     }
  1679.     
  1680.     if(IsItemLast(ItemBefore)) 
  1681.     {
  1682.         InsertItemLastInList(AList,ItemToInsert);
  1683.     }
  1684.     else
  1685.     {
  1686.         NextItem = GetNextItem(ItemBefore);
  1687.         PutPriorItem(ItemToInsert,ItemBefore);
  1688.         PutNextItem(ItemBefore,ItemToInsert);
  1689.         PutNextItem(ItemToInsert,NextItem);
  1690.         PutPriorItem(NextItem,ItemToInsert);
  1691.         AddToListItemCount(AList,1);
  1692.     }
  1693. }
  1694.  
  1695. /*------------------------------------------------------------
  1696. | NAME: InsertItemBeforeItemInList
  1697. |
  1698. | PURPOSE: To insert an item before an item in a list.
  1699. |
  1700. | DESCRIPTION: If the item to follow the one being inserted
  1701. | is '0', then insert the item as last in the list.
  1702. |
  1703. | EXAMPLE:  InsertItemBeforeItemInList(AList, ItemAfter,
  1704. |                                       ItemToInsert);
  1705. |
  1706. | NOTE: 
  1707. |
  1708. | ASSUMES: 
  1709. |
  1710. | HISTORY: 01.09.88 by Lee Malone
  1711. |          11.21.93 if 'ItemAfter' == 0 condition added
  1712. |
  1713. ------------------------------------------------------------*/
  1714. Nothing
  1715. InsertItemBeforeItemInList(AddressOfList AList,
  1716.                            AddressOfItem ItemAfter,
  1717.                            AddressOfItem ItemToInsert)
  1718. {
  1719.     AddressOfItem PriorItem;
  1720.  
  1721.     if(!ItemAfter) 
  1722.     {
  1723.         InsertItemLastInList(AList,ItemToInsert);
  1724.         return;
  1725.     }
  1726.     
  1727.     if(IsItemFirst(ItemAfter)) 
  1728.     {
  1729.         InsertItemFirstInList(AList,ItemToInsert);
  1730.     }
  1731.     else
  1732.     {
  1733.         PriorItem = GetPriorItem(ItemAfter);
  1734.         PutPriorItem(ItemToInsert,PriorItem);
  1735.         PutNextItem(PriorItem,ItemToInsert);
  1736.         PutNextItem(ItemToInsert,ItemAfter);
  1737.         PutPriorItem(ItemAfter,ItemToInsert);
  1738.         AddToListItemCount(AList,1);
  1739.     }
  1740. }
  1741.  
  1742. /*------------------------------------------------------------
  1743. | NAME: InsertItemFirstInList 
  1744. |
  1745. | PURPOSE: To insert the given extracted item as the first 
  1746. |          item in a list.
  1747. |
  1748. | DESCRIPTION:
  1749. |
  1750. | EXAMPLE:  InsertItemFirstInList(AList, ItemToInsert);
  1751. |
  1752. | NOTE: 
  1753. |
  1754. | ASSUMES: 
  1755. |
  1756. | HISTORY: 01.09.88 by Lee Malone
  1757. |
  1758. ------------------------------------------------------------*/
  1759. Nothing
  1760. InsertItemFirstInList(AddressOfList AList,
  1761.                       AddressOfItem AnItem)
  1762. {
  1763.     
  1764.     AddressOfItem FirstItem;
  1765.     
  1766.     MarkItemAsFirst(AnItem);
  1767.     
  1768.     if(IsAnyItemsInList(AList)) 
  1769.     {
  1770.         FirstItem = GetFirstItemOfList(AList);
  1771.         PutNextItem(AnItem,FirstItem);
  1772.         PutPriorItem(FirstItem,AnItem);
  1773.     }
  1774.     else
  1775.     {
  1776.         MarkItemAsLast(AnItem);
  1777.         PutLastItemOfList(AList,AnItem);
  1778.     }
  1779.     AddToListItemCount(AList,1);
  1780.     PutFirstItemOfList(AList,AnItem);
  1781. }
  1782.  
  1783. /*------------------------------------------------------------
  1784. | NAME: InsertItemLastInList
  1785. |
  1786. | PURPOSE: To append the given extracted item to a list.
  1787. |
  1788. | DESCRIPTION:
  1789. |
  1790. | EXAMPLE:  InsertItemLastInList(AList, ItemToInsert);
  1791. |
  1792. | NOTE: 
  1793. |
  1794. | ASSUMES: 
  1795. |
  1796. | HISTORY: 01.09.88 by Lee Malone
  1797. |
  1798. ------------------------------------------------------------*/
  1799. Nothing
  1800. InsertItemLastInList(AddressOfList AList,
  1801.                      AddressOfItem AnItem)
  1802. {
  1803.     
  1804.     AddressOfItem LastItem;
  1805.     
  1806.     MarkItemAsLast(AnItem);
  1807.     
  1808.     if(IsAnyItemsInList(AList)) 
  1809.     {
  1810.         LastItem = GetLastItemOfList(AList);
  1811.         PutPriorItem(AnItem,LastItem);
  1812.         PutNextItem(LastItem,AnItem);
  1813.     }
  1814.     else
  1815.     {
  1816.         MarkItemAsFirst(AnItem);
  1817.         PutFirstItemOfList(AList,AnItem);
  1818.     }
  1819.     AddToListItemCount(AList,1);
  1820.     PutLastItemOfList(AList,AnItem);
  1821. }
  1822.  
  1823. /*------------------------------------------------------------
  1824. | NAME: IsAnyItemMarkedInList
  1825. |
  1826. | PURPOSE: To tell if any item is marked in a list.
  1827. |
  1828. | DESCRIPTION:  Returns non-zero if any item is marked.
  1829. |
  1830. | EXAMPLE:  Result = IsAnyItemMarkedInList( AList );
  1831. |
  1832. | NOTE:  
  1833. |
  1834. | ASSUMES: 
  1835. |
  1836. | HISTORY: 10.18.91 by Lee Malone
  1837. |          12.19.91 fixed to handle empty lists
  1838. |          02.08.93 converted from list.txt
  1839. |          11.19.93 simplified logic
  1840. ------------------------------------------------------------*/
  1841. Truth
  1842. IsAnyItemMarkedInList(AddressOfList AList)
  1843. {
  1844.     Truth    Result;
  1845.     
  1846.     Result = False;
  1847.     
  1848.     PushTheListAndItem();
  1849.     
  1850.     TheList = AList;
  1851.     
  1852.     ToFirstItem();
  1853.     
  1854.     while(TheItem)
  1855.     {
  1856.         if( IsItemMarked(TheItem) )
  1857.         {
  1858.             Result = True;
  1859.             break;
  1860.         }
  1861.         ToNextItem();
  1862.     }
  1863.  
  1864.     PullTheListAndItem();
  1865.     
  1866.     return(Result);
  1867. }
  1868.  
  1869. /*------------------------------------------------------------
  1870. | NAME: IsAnyItemsInList
  1871. |
  1872. | PURPOSE: To tell if list has existing items.
  1873. |
  1874. | DESCRIPTION:
  1875. |
  1876. | EXAMPLE:  Result = IsAnyItemsInList( AList );
  1877. |
  1878. | NOTE: 
  1879. |
  1880. | ASSUMES: 
  1881. |
  1882. | HISTORY: 01.05.88 by Lee Malone
  1883. |
  1884. ------------------------------------------------------------*/
  1885. Truth
  1886. IsAnyItemsInList(AddressOfList AList)
  1887. {
  1888.     return( GetListItemCount(AList) );
  1889. }
  1890.  
  1891. /*------------------------------------------------------------
  1892. | NAME: IsItemAlone      
  1893. |
  1894. | PURPOSE: To tell if a item is the only one in a list.
  1895. |
  1896. | DESCRIPTION:If both next and prior are 0, and therefore equal, 
  1897. | then this is the only item.
  1898. |
  1899. | EXAMPLE:  if( IsItemAlone(AnItem) ) return(True);
  1900. |
  1901. | NOTE: 
  1902. |
  1903. | ASSUMES: 
  1904. |
  1905. | HISTORY: 01.04.88 by Lee Malone
  1906. |          07.12.89 revised
  1907. |
  1908. ------------------------------------------------------------*/
  1909. Truth
  1910. IsItemAlone(AddressOfItem AnItem)
  1911. {
  1912.     return( GetPriorItem(AnItem) == GetNextItem(AnItem)  );
  1913. }
  1914.  
  1915. /*------------------------------------------------------------
  1916. | NAME: IsItemCreationPossible      
  1917. |
  1918. | PURPOSE: To tell if a list can be created.
  1919. |
  1920. | DESCRIPTION:
  1921. |
  1922. | EXAMPLE:  IsItemCreationPossible();
  1923. |
  1924. | NOTE: 
  1925. |
  1926. | ASSUMES: 
  1927. |
  1928. | HISTORY: 07.19.89 by Lee Malone
  1929. |
  1930. ------------------------------------------------------------*/
  1931. Truth
  1932. IsItemCreationPossible()
  1933. {
  1934.     return( CountOfFreeItems );
  1935. }
  1936.  
  1937. /*------------------------------------------------------------
  1938. | NAME: IsItemFirst
  1939. |
  1940. | PURPOSE: To tell if a item is first in a list.
  1941. |
  1942. | DESCRIPTION:
  1943. |
  1944. | EXAMPLE:  if( IsItemFirst(AnItem) ) return(True);
  1945. |
  1946. | NOTE: 
  1947. |
  1948. | ASSUMES: 
  1949. |
  1950. | NOTE: If AddressOfPriorItem is 0, then item is first
  1951. |
  1952. | HISTORY: 01.04.88 by Lee Malone
  1953. |
  1954. ------------------------------------------------------------*/
  1955. Truth
  1956. IsItemFirst(AddressOfItem AnItem)
  1957. {
  1958.     return(!GetPriorItem(AnItem));
  1959. }
  1960.  
  1961. /*------------------------------------------------------------
  1962. | NAME: IsItemLast
  1963. |
  1964. | PURPOSE: To tell if a item is last in a list.
  1965. |
  1966. | DESCRIPTION: If AddressOfNextItem is 0 then it is the last 
  1967. |              item.
  1968. |
  1969. | EXAMPLE:  if( IsItemLast(AnItem) ) return(True);
  1970. |
  1971. | NOTE: 
  1972. |
  1973. | ASSUMES: 
  1974. |
  1975. | HISTORY: 01.04.88 by Lee Malone
  1976. |
  1977. ------------------------------------------------------------*/
  1978. Truth
  1979. IsItemLast(AddressOfItem AnItem)
  1980. {
  1981.     return(!GetNextItem(AnItem));
  1982. }
  1983.  
  1984. /*------------------------------------------------------------
  1985. | NAME: IsItemMarked
  1986. |
  1987. | PURPOSE: To tell if a item is marked.
  1988. |
  1989. | DESCRIPTION:
  1990. |
  1991. | EXAMPLE:  if( IsItemMarked(AnItem) ) UnMarkItem(AnItem);
  1992. |
  1993. | NOTE: 
  1994. |
  1995. | ASSUMES: 
  1996. |
  1997. | HISTORY: 07.12.89 by Lee Malone
  1998. |
  1999. ------------------------------------------------------------*/
  2000. Truth
  2001. IsItemMarked(AddressOfItem AnItem)
  2002. {
  2003.     return(GetItemMark(AnItem) & Marked);
  2004. }
  2005.  
  2006. /*------------------------------------------------------------
  2007. | NAME: IsListCreationPossible      
  2008. |
  2009. | PURPOSE: To tell if a list can be created.
  2010. |
  2011. | DESCRIPTION:
  2012. |
  2013. | EXAMPLE:  IsListCreationPossible();
  2014. |
  2015. | NOTE: 
  2016. |
  2017. | ASSUMES: 
  2018. |
  2019. | HISTORY: 07.19.89 by Lee Malone
  2020. |
  2021. ------------------------------------------------------------*/
  2022. Truth
  2023. IsListCreationPossible()
  2024. {
  2025.     return( CountOfFreeLists );
  2026. }
  2027.  
  2028. /*------------------------------------------------------------
  2029. | NAME: IsListMarked
  2030. |
  2031. | PURPOSE: To tell if list is marked.
  2032. |
  2033. | DESCRIPTION:
  2034. |
  2035. | EXAMPLE:  if( IsListMarked(AList) ) UnMarkList(AList);
  2036. |
  2037. | NOTE: 
  2038. |
  2039. | ASSUMES: 
  2040. |
  2041. | NOTE:
  2042. |
  2043. | HISTORY: 07.09.88 by Lee Malone
  2044. |
  2045. ------------------------------------------------------------*/
  2046. Truth
  2047. IsListMarked(AddressOfList ListAddress)
  2048. {
  2049.     return(GetListMark(ListAddress) & Marked);
  2050. }
  2051.  
  2052. /*------------------------------------------------------------
  2053. | NAME: IsTheDataMatching
  2054. |
  2055. | PURPOSE: To tell if a field in the data of the current 
  2056. |          item matches a given test value.
  2057. |
  2058. | DESCRIPTION:
  2059. |
  2060. | EXAMPLE:  
  2061. |
  2062. |    TheItem = SomeNameItem;
  2063. |
  2064. |    Result =  IsTheDataMatching((Pair) 0, 
  2065. |                                (Pair) 4, 
  2066. |                                (AddressOfByte) "John" )
  2067. |
  2068. | NOTE: 
  2069. |
  2070. | ASSUMES: 
  2071. |
  2072. | HISTORY: 10.23.89 by Lee Malone
  2073. |
  2074. ------------------------------------------------------------*/
  2075. Truth
  2076. IsTheDataMatching(Pair          FieldOffset, 
  2077.                   Pair          FieldWidth, 
  2078.                   AddressOfByte DataToMatch )
  2079. {
  2080.     AddressOfByte    FieldAddress;
  2081.     
  2082.     FieldAddress = TheDataAddress;
  2083.     
  2084.     return( IsMatchingBytes( (AddressOfByte) 
  2085.                              &FieldAddress[FieldOffset], 
  2086.                              DataToMatch, 
  2087.                              (Quad) FieldWidth ) );
  2088. }
  2089.  
  2090. /*------------------------------------------------------------
  2091. | NAME: JoinLists
  2092. |
  2093. | PURPOSE: To join two lists together to form one list.
  2094. |
  2095. | DESCRIPTION: The items of the follower list, are appended 
  2096. | to the leader list, and then the empty follower list is 
  2097. | deleted.
  2098. | EXAMPLE:  
  2099. |
  2100. |     JoinLists(ListA, ListB);
  2101. |
  2102. |     will result in the items from listB being tacked onto
  2103. |     the end of ListA and then the list record for ListB 
  2104. |     will be deleted.
  2105. | NOTE: 
  2106. |
  2107. | ASSUMES: 
  2108. |
  2109. | HISTORY: 12.11.91 by Lee Malone
  2110. |          10.29.93 ported from Focus project
  2111. ------------------------------------------------------------*/
  2112. Nothing
  2113. JoinLists ( AddressOfList LeaderList,
  2114.             AddressOfList FollowerList)
  2115. {
  2116.     AddressOfItem    LastItemOfLeader;
  2117.     AddressOfItem    FirstItemOfFollower;
  2118.     Pair            NewMark;
  2119.     
  2120.     /* If the FollowerList has no items then return. */
  2121.     if( !IsAnyItemsInList(FollowerList) ) return;
  2122.   
  2123.     LastItemOfLeader    = GetLastItemOfList(LeaderList);
  2124.     FirstItemOfFollower = GetFirstItemOfList(FollowerList);
  2125.  
  2126.     /* If the LeaderList has existing items */
  2127.     if( IsAnyItemsInList(LeaderList) )
  2128.     {
  2129.  
  2130.         /*
  2131.          * Link the next link of the leader list
  2132.          * to the beginning of the follower.
  2133.          */
  2134.         PutNextItem( LastItemOfLeader, FirstItemOfFollower );
  2135.         
  2136.         /*
  2137.          * Link the prior link of the follower list
  2138.          * to the end of the leader list.
  2139.          */
  2140.         PutPriorItem( FirstItemOfFollower, LastItemOfLeader );
  2141.     }
  2142.     else /* LeaderList is empty. */
  2143.     {
  2144.         /*
  2145.          * Set the first item pointer in the
  2146.          * destination list from the source list
  2147.          */
  2148.         PutFirstItemOfList(LeaderList, FirstItemOfFollower );
  2149.     }
  2150.     
  2151.     /*
  2152.      * Set the last item pointer in the
  2153.      * destination list from the source list
  2154.      */
  2155.     PutLastItemOfList( LeaderList, GetLastItemOfList(FollowerList));
  2156.     /*
  2157.      * Sum the counts of the two lists.
  2158.      */
  2159.     AddToListItemCount(LeaderList,
  2160.                        GetListItemCount(FollowerList));
  2161.     /*
  2162.      * OR the marks of the two lists
  2163.      */
  2164.     NewMark = GetListMark(LeaderList) | GetListMark(FollowerList);
  2165.     PutListMark(LeaderList,NewMark);
  2166.          
  2167.     /*
  2168.      * Clear the list count & pointers for the
  2169.      * follower list.
  2170.      */
  2171.     MarkListAsEmpty(FollowerList);
  2172.   
  2173.     /* Return the list record to the list pool for reuse. */
  2174.     DeleteList(FollowerList);
  2175. }     
  2176.  
  2177. /*------------------------------------------------------------
  2178. | NAME: MarkItem
  2179. |
  2180. | PURPOSE: To mark a item.
  2181. |
  2182. | DESCRIPTION:
  2183. |
  2184. | EXAMPLE:  MarkItem(AnItem);
  2185. |
  2186. | NOTE: 
  2187. |
  2188. | ASSUMES: 
  2189. |
  2190. | HISTORY: 07.18.89 by Lee Malone
  2191. |
  2192. ------------------------------------------------------------*/
  2193. Nothing
  2194. MarkItem(AddressOfItem AnItem)
  2195. {
  2196.     PutItemMark(AnItem, GetItemMark(AnItem)|Marked);
  2197. }
  2198.  
  2199. /*------------------------------------------------------------
  2200. | NAME: MarkItemAsFirst
  2201. |
  2202. | PURPOSE: To mark a item as first in a list.
  2203. |
  2204. | DESCRIPTION:
  2205. |
  2206. | EXAMPLE:  MarkItemAsFirst(AnItem);
  2207. |
  2208. | NOTE: 
  2209. |
  2210. | ASSUMES: 
  2211. |
  2212. | HISTORY: 01.09.88 by Lee Malone
  2213. |          07.10.89 new structure revision
  2214. |
  2215. ------------------------------------------------------------*/
  2216. Nothing
  2217. MarkItemAsFirst(AddressOfItem AnItem)
  2218. {
  2219.     PutPriorItem(AnItem,(AddressOfItem) 0);
  2220. }
  2221.  
  2222. /*------------------------------------------------------------
  2223. | NAME: MarkItemAsLast
  2224. |
  2225. | PURPOSE: To mark a item as last in a list.
  2226. |
  2227. | DESCRIPTION:
  2228. |
  2229. | EXAMPLE:  MarkItemAsLast(AnItem);
  2230. |
  2231. | NOTE: 
  2232. |
  2233. | ASSUMES: 
  2234. |
  2235. | HISTORY: 01.09.88 by Lee Malone
  2236. |          07.10.89 new structure revision
  2237. |
  2238. ------------------------------------------------------------*/
  2239. Nothing
  2240. MarkItemAsLast(AddressOfItem AnItem)
  2241. {
  2242.     PutNextItem(AnItem,0);
  2243. }
  2244.  
  2245. /*------------------------------------------------------------
  2246. | NAME: MarkList
  2247. |
  2248. | PURPOSE: To mark a list.
  2249. |
  2250. | DESCRIPTION: 
  2251. |
  2252. | EXAMPLE:  MarkList( AList );
  2253. |
  2254. | NOTE: 
  2255. |
  2256. | ASSUMES: 
  2257. |
  2258. | HISTORY: 07.19.89 by Lee Malone
  2259. |
  2260. ------------------------------------------------------------*/
  2261. Nothing
  2262. MarkList(AddressOfList AList)
  2263. {
  2264.     PutListMark(AList, GetListMark(AList) | Marked );
  2265. }
  2266.     
  2267. /*------------------------------------------------------------
  2268. | NAME: MarkListAsEmpty
  2269. |
  2270. | PURPOSE: To mark a list as having no items.
  2271. |
  2272. | DESCRIPTION: 
  2273. |
  2274. | EXAMPLE:  MarkListAsEmpty( AList );
  2275. |
  2276. | NOTE: 
  2277. |
  2278. | ASSUMES: 
  2279. |
  2280. | HISTORY: 01.04.89 by Lee Malone
  2281. |
  2282. ------------------------------------------------------------*/
  2283. Nothing
  2284. MarkListAsEmpty(AddressOfList AList)
  2285. {
  2286.     PutListItemCount(AList,(Quad) 0);
  2287.     PutFirstItemOfList(AList,(AddressOfItem) 0);
  2288.     PutLastItemOfList(AList,(AddressOfItem) 0);
  2289. }
  2290.  
  2291. /*------------------------------------------------------------
  2292. | NAME: OutputListOfStrings
  2293. |
  2294. | PURPOSE: To output strings attached to a list.
  2295. |
  2296. | DESCRIPTION: Each string is placed on a separate line.
  2297. | A blank line is printed after the list.
  2298. |
  2299. | EXAMPLE:  OutputListOfStrings( MyList, OutputFile );
  2300. |
  2301. | NOTE: 
  2302. |
  2303. | ASSUMES: Each string is able to fit on a single line.
  2304. |
  2305. | HISTORY: 01.13.88 by Lee Malone
  2306. |          02.08.93 removed item count control in favor of 
  2307. |                    TheItem being non-0.
  2308. |          11.08.93 added explicit stream parameter
  2309. ------------------------------------------------------------*/
  2310. Nothing
  2311. OutputListOfStrings(AddressOfList AList, 
  2312.                     FILE *OutputStream)
  2313. {
  2314.     PushTheListAndItem();
  2315.     
  2316.     TheList = AList;
  2317.     
  2318.     ToFirstItem();
  2319.     
  2320.     while(TheItem)
  2321.     {
  2322.         fprintf(OutputStream,"%s\n",
  2323.             (AddressOfString)TheDataAddress);
  2324.         ToNextItem();
  2325.     }
  2326.  
  2327.     fprintf(OutputStream,"\n");
  2328.  
  2329.     PullTheListAndItem();
  2330. }
  2331.  
  2332. /*------------------------------------------------------------
  2333. | NAME: OutputListSystemStatus
  2334. |
  2335. | PURPOSE: To report on list system status.
  2336. |
  2337. | DESCRIPTION:  
  2338. |
  2339. | EXAMPLE:  OutputListSystemStatus(OutputFile);
  2340. |
  2341. | NOTE: 
  2342. |
  2343. | ASSUMES: 
  2344. |
  2345. | HISTORY: 11.26.91 by Lee Malone
  2346. |          11.01.93 extended 
  2347. |          11.08.93 added 'OutputStream' parameter
  2348. ------------------------------------------------------------*/
  2349. Nothing
  2350. OutputListSystemStatus(FILE *OutputStream)
  2351. {
  2352.     AddressOfString    MarkString;
  2353.     
  2354.     fprintf(OutputStream,"\n");
  2355.     fprintf(OutputStream,"List System Status:\n");
  2356.     fprintf(OutputStream,"    TheListSystemIsSetUp...%d\n\n",
  2357.                          TheListSystemIsSetUp);
  2358.  
  2359.     fprintf(OutputStream,"    ListsInUse.............%ld\n",
  2360.                          (MaxCountOfLists-CountOfFreeLists));
  2361.     fprintf(OutputStream,"    ItemsInUse.............%ld\n\n",
  2362.                                   (MaxCountOfItems-CountOfFreeItems));
  2363.     fprintf(OutputStream,"    FreeLists..............%ld\n",
  2364.                                   CountOfFreeLists);
  2365.     fprintf(OutputStream,"    FreeItems..............%ld\n\n",
  2366.                                   CountOfFreeItems);
  2367.  
  2368.     fprintf(OutputStream,"    TheList................%lx\n",TheList);
  2369.     if(TheList)
  2370.     {
  2371.           fprintf(OutputStream,"        TheFirstItem.......%lx\n",
  2372.                                             TheFirstItem);
  2373.           fprintf(OutputStream,"        TheLastItem........%lx\n",
  2374.                                             TheLastItem);
  2375.           MarkString = "UnMarked";
  2376.           if(IsListMarked(TheList)) MarkString = "Marked";
  2377.           fprintf(OutputStream,"        TheListMark........%s\n",
  2378.                                                MarkString);
  2379.           fprintf(OutputStream,"        TheItemCount.......%ld\n\n",
  2380.                                             TheItemCount);
  2381.     }
  2382.     
  2383.     fprintf(OutputStream,"    TheItem................%lx\n",TheItem);
  2384.     if(TheItem)
  2385.     {
  2386.         fprintf(OutputStream,"        ThePriorItem.......%lx\n",
  2387.                                             ThePriorItem);
  2388.         fprintf(OutputStream,"        TheNextItem........%lx\n",
  2389.                                             TheNextItem);
  2390.         MarkString = "UnMarked";
  2391.         if(IsItemMarked(TheItem)) MarkString = "Marked";
  2392.         fprintf(OutputStream,"        TheItemMark........%s\n",
  2393.                                             MarkString);
  2394.         fprintf(OutputStream,"        TheDataAddress.....%lx\n",
  2395.                                             TheDataAddress);
  2396.     }
  2397. }
  2398.  
  2399. /*------------------------------------------------------------
  2400. | NAME: PullTheItem
  2401. |
  2402. | PURPOSE: To pull TheItem from TheListStack.
  2403. |
  2404. | DESCRIPTION:
  2405. |
  2406. | EXAMPLE:  PullTheItem();
  2407. |
  2408. | NOTE: 
  2409. |
  2410. | ASSUMES: 
  2411. |
  2412. | HISTORY: 01.04.89 by Lee Malone
  2413. |
  2414. ------------------------------------------------------------*/
  2415. Nothing
  2416. PullTheItem()
  2417. {
  2418.     TheItem = (AddressOfItem) 
  2419.               TheListStack[TheListStackIndex--];
  2420. }
  2421.  
  2422. /*------------------------------------------------------------
  2423. | NAME: PullTheList
  2424. |
  2425. | PURPOSE: To pull TheList from TheListStack.
  2426. |
  2427. | DESCRIPTION:
  2428. |
  2429. | EXAMPLE:  PullTheList();
  2430. |
  2431. | NOTE: 
  2432. |
  2433. | ASSUMES: 
  2434. |
  2435. | HISTORY: 01.04.89 by Lee Malone
  2436. |
  2437. ------------------------------------------------------------*/
  2438. Nothing
  2439. PullTheList()
  2440. {
  2441.     TheList = (AddressOfList) 
  2442.               TheListStack[TheListStackIndex--];
  2443. }
  2444.  
  2445. /*------------------------------------------------------------
  2446. | NAME: PullTheListAndItem
  2447. |
  2448. | PURPOSE: To pull The Item and TheList from TheListStack.
  2449. |
  2450. | DESCRIPTION:
  2451. |
  2452. | EXAMPLE:  PullTheListAndItem();
  2453. |
  2454. | NOTE: 
  2455. |
  2456. | ASSUMES: 
  2457. |
  2458. | HISTORY: 01.04.89 by Lee Malone
  2459. |
  2460. ------------------------------------------------------------*/
  2461. Nothing
  2462. PullTheListAndItem()
  2463. {
  2464.     PullTheItem();
  2465.     PullTheList();
  2466. }
  2467.  
  2468. /*------------------------------------------------------------
  2469. | NAME: PushTheItem
  2470. |
  2471. | PURPOSE: To save TheItem on TheListStack.
  2472. |
  2473. | DESCRIPTION:
  2474. |
  2475. | EXAMPLE:  PushTheItem()
  2476. |
  2477. | NOTE: 
  2478. |
  2479. | ASSUMES: 
  2480. |
  2481. | HISTORY: 01.04.89 by Lee Malone
  2482. |
  2483. ------------------------------------------------------------*/
  2484. Nothing
  2485. PushTheItem()
  2486. {
  2487.     TheListStack[++TheListStackIndex] = (Quad) TheItem;
  2488. }
  2489.  
  2490. /*------------------------------------------------------------
  2491. | NAME: PushTheList
  2492. |
  2493. | PURPOSE: To save TheList on TheListStack.
  2494. |
  2495. | DESCRIPTION:
  2496. |
  2497. | EXAMPLE:  PushTheList()
  2498. |
  2499. | NOTE: 
  2500. |
  2501. | ASSUMES: 
  2502. |
  2503. | HISTORY: 01.04.89 by Lee Malone
  2504. |
  2505. ------------------------------------------------------------*/
  2506. Nothing
  2507. PushTheList()
  2508. {
  2509.     TheListStack[++TheListStackIndex] = (Quad) TheList;
  2510. }
  2511.  
  2512. /*------------------------------------------------------------
  2513. | NAME: PushTheListAndItem
  2514. |
  2515. | PURPOSE: To save TheList and TheItem on TheListStack.
  2516. |
  2517. | DESCRIPTION:
  2518. |
  2519. | EXAMPLE:  PushTheListAndItem()
  2520. |
  2521. | NOTE: 
  2522. |
  2523. | ASSUMES: 
  2524. |
  2525. | HISTORY: 01.04.89 by Lee Malone
  2526. |
  2527. ------------------------------------------------------------*/
  2528. Nothing
  2529. PushTheListAndItem()
  2530. {
  2531.     PushTheList();
  2532.     PushTheItem();
  2533. }
  2534.  
  2535. /*------------------------------------------------------------
  2536. | NAME: ReorderListToMatchDirectAccessTable
  2537. |
  2538. | PURPOSE: To make the order of items in a list conform to
  2539. | the items in a DirectAccessTable.
  2540. |
  2541. | DESCRIPTION: After reordering a list via a direct access
  2542. | table it may be necessary to make the original list conform
  2543. | to the new ordering: this procedure does that.
  2544. |
  2545. | EXAMPLE:  ReorderListToMatchDirectAccessTable( 
  2546. |                    NameList,
  2547. |                   AlphaNameTable);
  2548. |
  2549. | NOTE: 
  2550. |
  2551. | ASSUMES: All items are contained in both the list
  2552. |          and the direct access table.
  2553. |
  2554. | HISTORY: 09.12.89 by Lee Malone
  2555. |          10.28.93 revised for speed.
  2556. |
  2557. ------------------------------------------------------------*/
  2558. Nothing
  2559. ReorderListToMatchDirectAccessTable( AddressOfList AList,
  2560.                                      AddressOfAddressOfItem Table )
  2561. {
  2562.     Quad            CountOfItems;
  2563.     Quad            IndexOfLastItem;
  2564.     Quad            Entry;
  2565.     AddressOfItem    PriorItem;
  2566.     AddressOfItem    NextItem;
  2567.     
  2568.     CountOfItems = GetListItemCount(AList);
  2569.     
  2570.     if( CountOfItems < 2) return;
  2571.  
  2572.     IndexOfLastItem = CountOfItems - 1;
  2573.     
  2574.     PushTheListAndItem();
  2575.     
  2576.     TheList = AList;
  2577.  
  2578.     /* Adjust the list record first. */    
  2579.     TheFirstItem = Table[0];
  2580.     TheLastItem  = Table[IndexOfLastItem];
  2581.     
  2582.     /* Adjust the item pointers for all items but the last. */
  2583.     PriorItem = 0;
  2584.     
  2585.     for( Entry = 0; Entry < IndexOfLastItem; Entry++ )
  2586.     {
  2587.         TheItem  = Table[Entry];
  2588.         NextItem = Table[Entry+1];
  2589.         
  2590.         ThePriorItem = PriorItem;
  2591.         TheNextItem  = NextItem;
  2592.         
  2593.         PriorItem = TheItem;
  2594.     }
  2595.     
  2596.     /* Adjust the last item. */
  2597.     TheItem      = Table[IndexOfLastItem];
  2598.     ThePriorItem = Table[IndexOfLastItem-1];
  2599.     TheNextItem  = 0;
  2600.  
  2601.     PullTheListAndItem();
  2602. }
  2603.  
  2604.  
  2605. /*------------------------------------------------------------
  2606. | NAME: ReverseList
  2607. |
  2608. | PURPOSE: To reverse the ordering of items in a list.
  2609. |
  2610. | DESCRIPTION:
  2611. |
  2612. | EXAMPLE:  ReverseList(AList);
  2613. |
  2614. | NOTE: 
  2615. |
  2616. | ASSUMES: 
  2617. |
  2618. | HISTORY: 11.02.93 by Lee Malone
  2619. |
  2620. ------------------------------------------------------------*/
  2621. Nothing
  2622. ReverseList(AddressOfList AList)
  2623. {
  2624.     AddressOfItem    NextItem;
  2625.     AddressOfItem    FirstItem;
  2626.     
  2627.     PushTheListAndItem();
  2628.     
  2629.     TheList = AList;
  2630.     ToFirstItem();
  2631.     
  2632.     while(TheItem)
  2633.     {
  2634.         /* Exchange the next and prior item addresses. */
  2635.         NextItem     = TheNextItem;
  2636.         TheNextItem  = ThePriorItem;
  2637.         ThePriorItem = NextItem;
  2638.         
  2639.         TheItem = NextItem;
  2640.     }
  2641.     
  2642.     /* Exchange the endpoint addresses in the list record. */
  2643.     FirstItem    = TheFirstItem;
  2644.     TheFirstItem = TheLastItem;
  2645.     TheLastItem  = FirstItem;
  2646.     
  2647.     PullTheListAndItem();
  2648. }
  2649.  
  2650. /*------------------------------------------------------------
  2651. | NAME: SetUpTheListSystem
  2652. |
  2653. | PURPOSE: To set up the list system for use.
  2654. |
  2655. | DESCRIPTION: Allocates memory space for subsequent use
  2656. | as list and item records.  This procedure sets an upper 
  2657. | limit on how many list or item records can be created.
  2658. |
  2659. | All available list records are linked together using their
  2660. | 'AddressOfFirstItem' fields and placed into the free list.
  2661. | A count of lists in the free list is maintained. There
  2662. | is no terminating 0 for the list: use 'CountOfFreeLists'
  2663. | instead to tell if the list is empty.
  2664. |
  2665. | All available item records are linked together using their
  2666. | 'AddressOfNextItem' fields and placed into the free item
  2667. | list. A count of items in the free list is maintained. 
  2668. | There is no terminating 0 for the list: use 
  2669. | 'CountOfFreeItems' instead to tell if the list is empty.
  2670. |
  2671. | EXAMPLE:  SetUpTheListSystem((Quad) HowManyLists, 
  2672. |                              (Quad) HowManyItems);
  2673. |
  2674. | NOTE: This procedure must be executed prior to running
  2675. |       any other procedure in the list system.
  2676. |
  2677. | ASSUMES: 
  2678. |
  2679. | HISTORY: 03.09.89 by Lee Malone
  2680. |          07.09.89 Changed to pre-allocate all possible 
  2681. |                   lists and items.
  2682. |          07.19.89 added free list
  2683. |
  2684. ------------------------------------------------------------*/
  2685. Nothing
  2686. SetUpTheListSystem(Quad MaximumLists, Quad MaximumItems)
  2687. {
  2688.     Quad SizeOfListSpace, SizeOfItemSpace,i;
  2689.  
  2690.     if( !TheListSystemIsSetUp )
  2691.     {
  2692.         TheListStackIndex = 0;
  2693.         
  2694.         MaxCountOfLists = MaximumLists;
  2695.         MaxCountOfItems = MaximumItems;
  2696.  
  2697.         SizeOfListSpace = MaxCountOfLists*sizeof(List);
  2698.         SizeOfItemSpace = MaxCountOfItems*sizeof(Item);
  2699.  
  2700.         ListSpace = AllocateMemory(SizeOfListSpace);
  2701.         if(ListSpace == 0) 
  2702.         {
  2703.             printf("Error: Unable to allocate list space.\n");
  2704.             exit(1);
  2705.         }
  2706.  
  2707.         ItemSpace = AllocateMemory(SizeOfItemSpace);
  2708.         if(ItemSpace == 0)
  2709.         {
  2710.             printf("Error: Unable to allocate item space.\n");
  2711.             exit(1);
  2712.         }
  2713.  
  2714.         CountOfFreeItems = MaxCountOfItems;
  2715.         CountOfFreeLists = MaxCountOfLists;
  2716.  
  2717.         FirstFreeList = ListSpace;
  2718.         FirstFreeItem = ItemSpace;
  2719.  
  2720.         /* Use the 'AddressOfFirstItem' field to link all free
  2721.            list records together.  
  2722.         */
  2723.         for( i = 0; i < MaxCountOfLists ; i++ )
  2724.         {
  2725.             ListSpace[i].AddressOfFirstItem = 
  2726.             (AddressOfItem) &ListSpace[i+1];
  2727.         }
  2728.  
  2729.         /* Use the 'AddressOfNextItem' field to link all free
  2730.            item records together.  
  2731.         */
  2732.         for( i = 0; i < MaxCountOfItems ; i++ )
  2733.         {
  2734.             ItemSpace[i].AddressOfNextItem = 
  2735.             (AddressOfItem) &ItemSpace[i+1];
  2736.         }
  2737.     }
  2738.     TheListSystemIsSetUp++;
  2739. }
  2740.  
  2741. /*------------------------------------------------------------
  2742. | NAME: SortDirectAccessTable
  2743. |
  2744. | PURPOSE: To sort a direct access table in ascending order.
  2745. |
  2746. | DESCRIPTION: Expects the address of a direct access table,
  2747. | a count of entries in the table, and the address of the
  2748. | comparison procedure to be used. 
  2749. |
  2750. | Uses fast Heap Sort procedure.
  2751. |
  2752. | A direct access table is an array of item record addresses.
  2753. |
  2754. | EXAMPLE:  
  2755. |
  2756. | SortDirectAccessTable( ATable, 
  2757. |                        EntryCount, 
  2758. |                        CompareStrings );
  2759. |
  2760. | NOTE: Especially well suited to long tables as the run time
  2761. | is proportional to Nlog2N as a worst case, eg. a 256 element
  2762. | list would take time proportional to 256*8 = 2048 vs.
  2763. | N*N or 64K for the bubble sort.
  2764. |
  2765. | ASSUMES: 
  2766. |
  2767. | NOTE: See "Numerical Recipes, The Art of Scientific 
  2768. |        Computing", page 229, for complete explanation. 
  2769. |
  2770. | HISTORY: 09.12.89 by Lee Malone
  2771. |          12.22.91 revised to use Heap Sort algorithm.
  2772. |          11.02.93 ported from Focus.
  2773. |
  2774. ------------------------------------------------------------*/
  2775. Nothing
  2776. SortDirectAccessTable( 
  2777.     AddressOfAddressOfItem          ATable, 
  2778.     Quad                            TableCount, 
  2779.     AddressOfComparisonProcedure ComparisonProcedure)
  2780. {
  2781.     AddressOfByte  AData;
  2782.     AddressOfByte  BData;
  2783.     AddressOfItem  EntryBeingMoved;
  2784.     Comparison       ComparisonResult;
  2785.     Quad           HeapIndexL;
  2786.     Quad           HeapIndexIR;
  2787.     Quad           HeapIndexI;
  2788.     Quad           HeapIndexJ;
  2789.     
  2790.     if(TableCount < 2) return;
  2791.     
  2792.     HeapIndexL  = (TableCount >> 1) + 1; 
  2793.     HeapIndexIR = TableCount;
  2794.     
  2795.     while(1)
  2796.     {
  2797.         if(HeapIndexL > 1)
  2798.         {
  2799.             HeapIndexL--;
  2800.             EntryBeingMoved = ATable[HeapIndexL-1];
  2801.         }
  2802.         else
  2803.         {
  2804.             EntryBeingMoved = ATable[HeapIndexIR-1];
  2805.             ATable[HeapIndexIR-1] = ATable[0];
  2806.             HeapIndexIR--;
  2807.             if( HeapIndexIR == 1 ) /* at the end */
  2808.             {               
  2809.                 ATable[0] = EntryBeingMoved;
  2810.                    return;
  2811.             }
  2812.         }
  2813.         
  2814.         HeapIndexI = HeapIndexL;
  2815.         HeapIndexJ = HeapIndexL<<1;
  2816.         
  2817.         while( HeapIndexJ <= HeapIndexIR )
  2818.         {
  2819.             if( HeapIndexJ < HeapIndexIR )
  2820.             {
  2821.                 AData = GetItemDataAddress(ATable[HeapIndexJ-1]);
  2822.                 BData = GetItemDataAddress(ATable[HeapIndexJ]);
  2823.  
  2824.                   ComparisonResult  = 
  2825.                     (*ComparisonProcedure)(AData,BData);
  2826.                   
  2827.                 if( ComparisonResult < 0 )
  2828.                 {
  2829.                     HeapIndexJ++;
  2830.                 }
  2831.             }
  2832.             
  2833.             AData = GetItemDataAddress(EntryBeingMoved);
  2834.             BData = GetItemDataAddress(ATable[HeapIndexJ-1]);
  2835.  
  2836.             ComparisonResult = (*ComparisonProcedure)(AData,BData);
  2837.                   
  2838.             if( ComparisonResult < 0 )
  2839.             {
  2840.               
  2841.               ATable[HeapIndexI-1] = ATable[HeapIndexJ-1];
  2842.               HeapIndexI = HeapIndexJ;
  2843.               HeapIndexJ += HeapIndexJ;
  2844.             }
  2845.             else
  2846.             {
  2847.               HeapIndexJ = HeapIndexIR+1;
  2848.             }
  2849.         }
  2850.         
  2851.         ATable[HeapIndexI - 1] = EntryBeingMoved;
  2852.     }
  2853. }
  2854.  
  2855. /*------------------------------------------------------------
  2856. | NAME: SortList
  2857. |
  2858. | PURPOSE: To sort a list in ascending order using a given 
  2859. | comparison procedure.
  2860. |
  2861. | DESCRIPTION: Uses one of two algorithms depending on the
  2862. | length of the list:
  2863. |
  2864. | 1. For lists with more items than 'DirectAccessTableThreshold',
  2865. |    the list is sorted by way of a direct access table using a
  2866. |    HeapSort algorithm.
  2867. |
  2868. | 2. Shorter lists use a simple, slower bubble sort algorithm.
  2869. |
  2870. | EXAMPLE:  SortList( ListOfNames, CompareStrings );
  2871. |
  2872. | NOTE: See 'CompareStrings' for an example of a comparison
  2873. | procedure.  Use it as a template for other comparison 
  2874. | procedures.
  2875. |
  2876. | ASSUMES: 
  2877. |
  2878. | NOTE: 
  2879. |
  2880. | HISTORY: 11.02.93 by Lee Malone
  2881. |
  2882. ------------------------------------------------------------*/
  2883. Nothing
  2884. SortList(AddressOfList AList,
  2885.          AddressOfComparisonProcedure ComparisonProcedure)
  2886. {
  2887.         
  2888.     if( GetListItemCount(AList) > DirectAccessTableThreshold )
  2889.     {
  2890.         SortListViaDirectAccessTable(
  2891.             AList,
  2892.             ComparisonProcedure);
  2893.     }
  2894.     else
  2895.     {
  2896.         SortShortList(AList,ComparisonProcedure);
  2897.     }
  2898. }
  2899.  
  2900. /*------------------------------------------------------------
  2901. | NAME: SortListAlphabetically
  2902. |
  2903. | PURPOSE: To sort a list alphabetically.
  2904. |
  2905. | DESCRIPTION:
  2906. |
  2907. | EXAMPLE:  SortListAlphabetically( ListOfNames );
  2908. |
  2909. | NOTE: 
  2910. |
  2911. | ASSUMES: 
  2912. |
  2913. | NOTE: Case insensitive.
  2914. |
  2915. | HISTORY: 01.13.89 by Lee Malone
  2916. |          11.02.93 revised to call 'SortList'.
  2917. |
  2918. ------------------------------------------------------------*/
  2919. Nothing
  2920. SortListAlphabetically(AddressOfList AList)
  2921. {
  2922.     AddressOfComparisonProcedure ComparisonProcedure;
  2923.  
  2924.     ComparisonProcedure = (AddressOfComparisonProcedure)
  2925.                           CompareStrings;
  2926.         
  2927.     SortList(AList,ComparisonProcedure);
  2928. }
  2929.  
  2930. /*------------------------------------------------------------
  2931. | NAME: SortListDescending
  2932. |
  2933. | PURPOSE: To sort a list in descending order.
  2934. |
  2935. | DESCRIPTION: Pass the comparison function to be used.  
  2936. |        
  2937. |
  2938. | EXAMPLE:  SortListDescending( ListOfNames, CompareStrings );
  2939. |
  2940. | NOTE: 
  2941. |
  2942. | ASSUMES: 
  2943. |
  2944. | HISTORY: 01.11.89 by Lee Malone
  2945. |          09.14.89 BackCount added.
  2946. |          11.02.93 revised to use 'ReverseList'.
  2947. ------------------------------------------------------------*/
  2948. Nothing
  2949. SortListDescending(AddressOfList AList,
  2950.     AddressOfComparisonProcedure ComparisonProcedure)
  2951. {
  2952.     SortList(AList,ComparisonProcedure);
  2953.     ReverseList(AList);
  2954. }
  2955.  
  2956. /*------------------------------------------------------------
  2957. | NAME: SortListViaDirectAccessTable
  2958. |
  2959. | PURPOSE: To sort a list in ascending order by first 
  2960. | creating a direct access table.
  2961. |
  2962. | DESCRIPTION: Pass the comparison function to be used. Uses 
  2963. | fast heap sort algorithm.
  2964. | Creates a direct access table, sorts it, conforms list to
  2965. | ordering of the table, then discards the table.  
  2966. |
  2967. | Primarily for use with long lists.
  2968. |
  2969. | EXAMPLE:  
  2970. |        SortListViaDirectAccessTable( ListOfNames, 
  2971. |                                      CompareStrings );
  2972. | NOTE: 
  2973. |
  2974. | ASSUMES: Enough memory exists for direct access table 
  2975. |          built by this procedure.
  2976. |
  2977. | HISTORY: 09.12.89 by Lee Malone
  2978. |
  2979. ------------------------------------------------------------*/
  2980. Nothing
  2981. SortListViaDirectAccessTable( AddressOfList AList, 
  2982.     AddressOfComparisonProcedure ComparisonProcedure)
  2983. {
  2984.     AddressOfAddressOfItem     TablePointer;
  2985.     
  2986.     TablePointer = BuildDirectAccessTableForList( AList );
  2987.     
  2988.     SortDirectAccessTable( TablePointer, 
  2989.                            GetListItemCount(AList), 
  2990.                            ComparisonProcedure );
  2991.  
  2992.     ReorderListToMatchDirectAccessTable( AList, 
  2993.                                          TablePointer ); 
  2994.  
  2995.     FreeMemory( TablePointer );
  2996. }
  2997.  
  2998. /*------------------------------------------------------------
  2999. | NAME: SortShortList
  3000. |
  3001. | PURPOSE: To sort a given list in ascending order using 
  3002. | a given comparison procedure.
  3003. |
  3004. | DESCRIPTION: Uses simple but slow bubble sort function.  
  3005. | Doesn't require any additional storage.
  3006. |
  3007. | EXAMPLE:  SortShortList( ListOfNames, CompareStrings );
  3008. |
  3009. | NOTE: Use for short lists only.
  3010. |
  3011. | ASSUMES: 
  3012. |
  3013. | NOTE: 
  3014. |
  3015. | HISTORY: 01.11.89 by Lee Malone
  3016. |          09.14.89 BackCount added.
  3017. |
  3018. ------------------------------------------------------------*/
  3019. Nothing
  3020. SortShortList(AddressOfList      AList,
  3021.     AddressOfComparisonProcedure ComparisonProcedure)
  3022. {
  3023.     Truth             IsInOrder;
  3024.     AddressOfByte   AddressOfDataFromNextItem;
  3025.     AddressOfItem   AddressOfNextItem;
  3026.     Comparison      ComparisonResult;
  3027.     Quad            Repetitions,BackCount;
  3028.     
  3029.     if( GetListItemCount(AList) < 2 ) return;
  3030.     
  3031.     PushTheListAndItem();
  3032.     
  3033.     TheList = AList;
  3034.     
  3035.     IsInOrder = 0;
  3036.  
  3037.     BackCount = 1;
  3038.     
  3039.     while(IsInOrder == 0)
  3040.     {
  3041.         IsInOrder = 1;
  3042.         ToFirstItem();
  3043.         Repetitions = TheItemCount - BackCount++;
  3044.         while(Repetitions--)
  3045.         {
  3046.             AddressOfNextItem         = TheNextItem;
  3047.             AddressOfDataFromNextItem = 
  3048.                     GetItemDataAddress(AddressOfNextItem);
  3049.             ComparisonResult        = 
  3050.                 (*ComparisonProcedure)
  3051.                 (TheDataAddress,AddressOfDataFromNextItem);
  3052.                 
  3053.             if(ComparisonResult > 0)
  3054.             {
  3055.                 ExchangeItems(TheList,TheItem,AddressOfNextItem);
  3056.                 IsInOrder = 0;
  3057.             }
  3058.             else
  3059.             {
  3060.                 ToNextItem();
  3061.             }
  3062.         }
  3063.     }
  3064.     PullTheListAndItem();
  3065. }
  3066.  
  3067. /*------------------------------------------------------------
  3068. | NAME: ToFirstItem
  3069. |
  3070. | PURPOSE: To set the current item to be the first item in
  3071. |          the current list.
  3072. |
  3073. | DESCRIPTION: 
  3074. |
  3075. | EXAMPLE:  
  3076. |          TheList = ListOfNames;
  3077. |          ToFirstItem();
  3078. |
  3079. |          while(TheItem)
  3080. |          {
  3081. |               ConvertStringToUpperCase(
  3082. |                    (AddressOfString)TheDataAddress);
  3083. |               ToNextItem();
  3084. |          }
  3085. |
  3086. | NOTE: 
  3087. |
  3088. | ASSUMES: 
  3089. |
  3090. | HISTORY: 01.04.89 by Lee Malone
  3091. |
  3092. ------------------------------------------------------------*/
  3093. Nothing
  3094. ToFirstItem()
  3095. {
  3096.     TheItem = TheFirstItem;
  3097. }
  3098.  
  3099. /*------------------------------------------------------------
  3100. | NAME: ToLastItem
  3101. |
  3102. | PURPOSE: To set the current item to be the last item in
  3103. |          the current list.
  3104. |
  3105. | DESCRIPTION: 
  3106. |
  3107. | EXAMPLE:  
  3108. |          TheList = ListOfNames;
  3109. |          ToLastItem();
  3110. |
  3111. |          while(TheItem)
  3112. |          {
  3113. |               ConvertStringToUpperCase(
  3114. |                    (AddressOfString)TheDataAddress);
  3115. |                ToPriorItem();
  3116. |           }
  3117. |
  3118. | NOTE: 
  3119. |
  3120. | ASSUMES: 
  3121. |
  3122. | HISTORY: 01.04.89 by Lee Malone
  3123. |
  3124. ------------------------------------------------------------*/
  3125. Nothing
  3126. ToLastItem()
  3127. {
  3128.     TheItem = TheLastItem;
  3129. }
  3130.  
  3131. /*------------------------------------------------------------
  3132. | NAME: ToNextItem
  3133. |
  3134. | PURPOSE: To set the current item to be the next item in
  3135. |          the current list.
  3136. |
  3137. | DESCRIPTION: A list traversal operation.
  3138. |
  3139. | EXAMPLE:  
  3140. |          TheList = ListOfNames;
  3141. |          ToFirstItem();
  3142. |
  3143. |          while(TheItem)
  3144. |          {
  3145. |               ConvertStringToUpperCase(
  3146. |                    (AddressOfString)TheDataAddress);
  3147. |                ToNextItem();
  3148. |           }
  3149. |
  3150. | NOTE: 
  3151. |
  3152. | ASSUMES: 
  3153. |
  3154. | HISTORY: 01.04.89 by Lee Malone
  3155. |
  3156. ------------------------------------------------------------*/
  3157. Nothing
  3158. ToNextItem()
  3159. {
  3160.     TheItem = GetNextItem(TheItem);
  3161. }
  3162.  
  3163. /*------------------------------------------------------------
  3164. | NAME: ToPriorItem
  3165. |
  3166. | PURPOSE: To set a new current item via AddressOfPriorItem 
  3167. | from TheItem.
  3168. |
  3169. | DESCRIPTION: A list traversal operation.
  3170. |
  3171. | EXAMPLE:  
  3172. |          TheList = ListOfNames;
  3173. |          ToLastItem();
  3174. |
  3175. |          while(TheItem)
  3176. |          {
  3177. |               ConvertStringToUpperCase(
  3178. |                    (AddressOfString)TheDataAddress);
  3179. |                ToPriorItem();
  3180. |           }
  3181. |
  3182. | NOTE: 
  3183. |
  3184. | ASSUMES: 
  3185. |
  3186. | HISTORY: 01.04.89 by Lee Malone
  3187. |
  3188. ------------------------------------------------------------*/
  3189. Nothing
  3190. ToPriorItem()
  3191. {
  3192.     TheItem = GetPriorItem(TheItem);
  3193. }
  3194.  
  3195. /*------------------------------------------------------------
  3196. | NAME: UnMarkAllItemsInList
  3197. |
  3198. | PURPOSE: To clear item marks on all items in a list.
  3199. |
  3200. | DESCRIPTION:  Item marks may be used to separate some items
  3201. | from others in a list, e.g. to show which ones are selected. 
  3202. |
  3203. | EXAMPLE:  UnMarkAllItemsInList(AList);
  3204. |
  3205. | NOTE:  
  3206. |
  3207. | ASSUMES: 
  3208. |
  3209. | HISTORY: 10.08.91 by Lee Malone
  3210. |          02.08.93 from list.txt
  3211. ------------------------------------------------------------*/
  3212. Nothing
  3213. UnMarkAllItemsInList(AddressOfList ListAddress)
  3214. {
  3215.     PushTheListAndItem();
  3216.     
  3217.     TheList = ListAddress;
  3218.     
  3219.     ToFirstItem();
  3220.     
  3221.     while(TheItem)
  3222.     {
  3223.         UnMarkItem(TheItem);
  3224.         ToNextItem();
  3225.     }
  3226.  
  3227.     PullTheListAndItem();
  3228. }
  3229.  
  3230. /*------------------------------------------------------------
  3231. | NAME: UnMarkItem
  3232. |
  3233. | PURPOSE: To unmark a item.
  3234. |
  3235. | DESCRIPTION:
  3236. |
  3237. | EXAMPLE:  UnMarkItem(AnItem);
  3238. |
  3239. | NOTE: 
  3240. |
  3241. | ASSUMES: 
  3242. |
  3243. | HISTORY: 07.18.89 by Lee Malone
  3244. |
  3245. ------------------------------------------------------------*/
  3246. Nothing
  3247. UnMarkItem(AddressOfItem AnItem)
  3248. {
  3249.     PutItemMark(AnItem, GetItemMark(AnItem) & ~Marked);
  3250. }
  3251.  
  3252. /*------------------------------------------------------------
  3253. | NAME: UnMarkList
  3254. |
  3255. | PURPOSE: To unmark a list.
  3256. |
  3257. | DESCRIPTION: 
  3258. |
  3259. | EXAMPLE:  UnMarkList(AList);
  3260. |
  3261. | NOTE: 
  3262. |
  3263. | ASSUMES: 
  3264. |
  3265. | HISTORY: 07.19.89 by Lee Malone
  3266. |
  3267. ------------------------------------------------------------*/
  3268. Nothing
  3269. UnMarkList(AddressOfList AList)
  3270. {
  3271.     PutListMark(AList, GetListMark(AList) & ~Marked );
  3272. }
  3273.  
  3274.